Подтвердить что ты не робот

Изменение набора правил CSS из Javascript

Возможно ли внести изменения в набор правил CSS динамически (т.е. некоторые JS, которые изменят набор правил CSS, когда пользователь нажимает на виджет)

Этот конкретный набор правил CSS применяется к множеству элементов (через селектор классов) на странице, и я хочу изменить его, когда пользователь нажимает на виджет, так что все элементы, имеющие класс, изменяются.

4b9b3361

Ответ 1

Вы можете, но это довольно громоздко. Лучшая ссылка на то, как это сделать, следующая статья: Полностью Pwn CSS с Javascript (ссылка на веб-архив).

Мне удалось заставить его работать с Firefox и IE - Я не мог в Chrome, хотя кажется, что он поддерживает методы DOM. ricosrealm сообщает, что он также работает в Chrome.

Ответ 2

Это современная версия, основанная на Totally Pwn CSS с Javascript. Это ES6 Надеюсь, не против.

function getCSSRule(ruleName) {
    ruleName = ruleName.toLowerCase();
    var result = null;
    var find = Array.prototype.find;

    find.call(document.styleSheets, styleSheet => {
        result = find.call(styleSheet.cssRules, cssRule => {
            return cssRule instanceof CSSStyleRule 
                && cssRule.selectorText.toLowerCase() == ruleName;
        });
        return result != null;
    });
    return result;
}

Эта функция возвращает CSSStyleRule, который вы можете использовать следующим образом:

var header = getCSSRule('#header');
header.style.backgroundColor = 'red';

Также document.styleSheets ссылаются на список объектов CSSStylesSheets. Другим способом доступа к определенному файлу sytleSheet на странице является присвоение id элементу style или link в html-коде и его получение в javascript, используя document.getElementById('my-style'). sheet. Это несколько полезных методов:

Основные браузеры и IE9 +: insertRule(), deleteRule(), removeProperty().

Основные браузеры, Firefox? и IE9 +: setProperty().

<stye id="my-style" ...
....
var myStyle = document.getElementById('my-style').sheet
myStyle.insertRule('#header { background: red; }', 0);

Также возможно динамически создавать новый элемент стиля для хранения динамически созданных стилей, я думаю, что это должен быть способ избежать конфликтов.

Ответ 3

API-интерфейсы для редактирования таблиц стилей с JS, к сожалению, несовместимы между браузерами. утилита YUI Stylesheet Utility пытается сгладить эти различия, чтобы вы могли просто использовать это. Вы также можете посмотреть исходный код, чтобы выяснить, как это работает, если вы не хотите использовать сам YUI.

Ответ 4

Я пробовал код по ссылке из комментария @alex-gyoshev, но он не работает

  • он не работает в правилах CSS с помощью шрифтов Google в Chrome
  • он не справляется с проверками безопасности FireFox.

Итак, я немного изменил его, но удалил функциональность delete, поскольку он мне не нужен. Проверено в IE 11, FireFox 32, Chrome 37 и Opera 26.

function getCSSRule(ruleName) { // Return requested style object
  ruleName = ruleName.toLowerCase(); // Convert test string to lower case.
  var styleSheet;
  var i, ii;
  var cssRule = false; // Initialize cssRule. 
  var cssRules;
  if (document.styleSheets) { // If browser can play with stylesheets
    for (i = 0; i < document.styleSheets.length; i++) { // For each stylesheet
      styleSheet = document.styleSheets[i];
      if (!styleSheet.href) {
        if (styleSheet.cssRules) { // Browser uses cssRules?
          cssRules = styleSheet.cssRules; // Yes --Mozilla Style
        } else { // Browser usses rules?
          cssRules = styleSheet.rules; // Yes IE style. 
        } // End IE check.
        if (cssRules) {
          for (ii = 0; ii < cssRules.length; ii++) {
            cssRule = cssRules[ii];
            if (cssRule) { // If we found a rule...
              // console.log(cssRule);
              if (cssRule.selectorText) {
                console.log(cssRule.selectorText);
                if (cssRule.selectorText.toLowerCase() == ruleName) { //  match ruleName?
                  return cssRule; // return the style object.
                }
              }
            }
          }
        }
      }
    }
  }
  return false; // we found NOTHING!
}

Ответ 5

В зависимости от того, чего вы пытаетесь достичь, лучшим решением может быть изменение/добавление класса в содержащий элемент (тело будет делать!) и соответственно определить классы.

.yourclass { color: black }
#wrapper.foo .yourclass { color: red }
#waraper.bar .yourclass { color: blue }

то вы можете просто использовать

document.getElementById('wrapper').className='foo';

(или ваш выбранный фреймворк js для этого же), чтобы изменить все с помощью класса yourclass внутри любого вашего элемента wrapper.

((в скобках) есть ли способ остановить форматирование SO из предположения, что материал, начинающийся с #, является комментарием?)

Ответ 6

укажите свой тег стиля id, например <style id="ssID"> если someonelse делает ваши стили для вас скажите этому человеку, чтобы дать тегу стиля id - таким образом вы можете получить к нему доступ напрямую без скремблируя вокруг, задаваясь вопросом, что его индекс

// create a hash table
var cssHash = {};

// loop through and populate the hash table
for (let i in (r = ss0.sheet.rules)) {

    // selectorText is the name of the rule - set the value equal to the rule
    cssHash[r[i].selectorText] = r[i];

}

теперь у вас есть хеш-таблица для всего, что содержится в таблице стилей - обратите внимание, что некоторые значения будут undefined, но не для любая из вещей, о которых вы заботитесь

если у вас есть, например, класс с именем #menuItem и вы хотите изменить свой цвет на черный, сделайте это

cssHash['#menuItem'].style.color = #000;

эта строка установит цвет стиля правила индекс которого был просмотрен в хэш-таблице (cssHash) по имени "#menuItem"

что более важно, у вас, вероятно, есть несколько разных классы, которые вы хотите изменить сразу вроде как, когда вы меняли майоры в колледже

скажем, у вас есть четыре разных класса и вы хотите установить все цвета фона к тому же значению, что некоторый пользователь, выбранный из ввода

тег цветового селектора <input id="bColor" type="color"> и правила класса, которые вы хотите изменить, называются #menuItem. homeAddr span и #vacuum: hover

// create a listener for that color selector
bColor.addEventListener('input', function (e) {

  // loop through a split list of the four class names
  '#menuItem .homeAddr span #vacuum:hover'.split(' ').forEach(function (obj) {

    // use the hash table to look up the index of each name
    // and set the background color equal to the color input value
    cssHash[obj].style.backgroundColor = bColor.value;

  });

}, false); // false added here for the sake of non-brevity

Ответ 7

В то время как setAttribute приятный, в большинстве браузеров есть стандартный способ:

htmlElement.className = 'someClass';

Чтобы сделать это по многим элементам, вам понадобится кросс-браузерное решение:

function getElementsByClassName( className, context, tagName ) {
  context = context || document;
  if ( typeof context.getElementsByClassName === 'function' )
    return context.getElementsByClassName( className );

  if ( typeof context.getElementsByTagName !== 'function' )
    return [];

  var elements = typeof tagName === 'string' ? context.getElementsByTagName( tagName ) :
    context.getElementsByTagName('*'),
  ret = [];
  for ( var i = 0, il = elements.length; i < il; i++ )
    if ( elements[ i ].className.match( className ) )
      ret.push( elements[ i ] );

  return ret;
}

var elements = getElementsByClassName('someClass');

for ( var i = 0, il = elements.length; i < il; i++ )
  elements[ i ].className = 'newClass';

Вы можете заменить строку:

if ( elements[ i ].className.match( className ) )

С некоторым регулярным выражением, но вам придется избегать специальных символов в этом случае.