Изменение набора правил CSS из Javascript - PullRequest
57 голосов
/ 11 сентября 2009

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

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

Ответы [ 8 ]

33 голосов
/ 11 сентября 2009

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

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

7 голосов
/ 23 апреля 2016

Это современная версия, основанная на 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 ( 'мой стиль'). лист . Вот несколько полезных методов:

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

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

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

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

4 голосов
/ 07 октября 2014

Я попробовал код по ссылке из комментария @ 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!
}
4 голосов
/ 11 сентября 2009

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

3 голосов
/ 11 сентября 2009

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

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

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

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

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

1 голос
/ 02 апреля 2019

Вы можете редактировать CLASS в таблицах стилей документа следующим образом

[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
     .style.background= 'red';

function edit() {
  [...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
    .style.background= 'red';
}
.box {
  margin: 10px;
  padding: 10px;
  background: yellow;
}
<button onclick="edit()" >Click me</button>
<div class="box" >My box 1</div>
<div class="box" >My box 2</div>
<div class="box" >My box 3</div>
1 голос
/ 22 апреля 2017

присвойте тегу стиля идентификатор, например <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) по имени '# menuItem'

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

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

тег выбора цвета <input id="bColor" type="color"> и правила класса, которые вы хотите изменить, называются # menuItem .homeAddr span и # вакуум: 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's value
    cssHash[obj].style.backgroundColor = bColor.value;

  });

}, false); // false added here for the sake of non-brevity
0 голосов
/ 11 сентября 2009

Хотя 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 ) )

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...