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


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

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

7 52

7 ответов:

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

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

это современная версия, основанная на полностью 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';

и документ.таблицы стилей список ссылок на объекты CSSStylesSheets. Другой способ доступа к определенному системному листу на странице-это присвоение id до стиль или ссылке элемент в html-коде, и получить его javascript с помощью документ.метода getElementById('мой стиль').лист. Вот некоторые полезные методы:

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

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

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

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

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

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

  1. он не работает по правилам CSS с Google шрифтами в Chrome
  2. он терпит неудачу при проверке безопасности 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!
}

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

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

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

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

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

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

// 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) по имени '#меню'

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

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

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

// 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's value
    cssHash[obj].style.backgroundColor = bColor.value;

  });

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

пока 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 ) )

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