是否可以动态更改CSS规则集(例如,当用户单击窗口小部件时,某些JS会更改CSS规则集)

此特定CSS规则集适用于很多页面上的元素(通过类选择器)的集合,我想在用户单击窗口小部件时对其进行修改,以使具有类的所有元素都发生更改。

评论

查看一些答案,您的问题似乎有些困惑。 “ CSS类”不存在这一事实并没有帮助,但是通常会用这种方式错误地描述两个不同的事物。一个是“ HTML类”,但我认为您是指另一个-CSS规则集(在这种情况下,带有类选择器)。

我的意思是为类选择器提供CSS规则集

相关-从JavaScript设置CSS伪类规则

#1 楼

可以,但是很麻烦。关于如何执行此操作的最佳参考是以下文章:带有Javascript的完全Pwn CSS(网络存档链接)。

我设法使其与Firefox和IE兼容-我无法在Chrome中使用,尽管它似乎支持DOM方法。ricosrealm报告它也可以在Chrome中使用。

评论


这是来自MDC的一些参考:developer.mozilla.org/en/DOM/document.styleSheets developer.mozilla.org/En/DOM/Stylesheet

–法比奥
10-4-16在12:19



在Chrome 11中进行了测试。效果很好。

–ricosrealm
2011年6月23日在21:29

该指南真棒!!!我已经在最新的Firefox和Chrome上对其进行了测试,它的工作原理很吸引人!!!

–lucaferrario
2012年6月6日的1:02

链接已断开(数据库断开),但看起来好像有人将其转换为库。

– David Harkness
16 Mar 24 '16 at 19:10

这个答案已经过时了。在这里查看现代解决方案

– Zach Saucier
16年6月30日在21:07

#2 楼

这是基于带有Javascript的Totally Pwn CSS的现代版本。我希望是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的其他方法是为HTML代码中的样式或链接元素分配一个ID,然后使用document.getElementById('my-style')。sheet在javascript中获取它。这是一些有用的方法:

主要浏览器和IE9 +:insertRule(),deleteRule(),removeProperty()。

主流浏览器,Firefox?和IE9 +:setProperty()。

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


也可以动态创建新样式元素来存储动态创建的样式,我认为应该是避免冲突的方法。

评论


这很棒!我只需要在调用find之前添加对styleSheet.cssRules是否存在的检查。

–沙地关节
17-10-18在21:11

#3 楼

我通过@ alex-gyoshev注释中的链接尝试了代码,但是它不起作用


在Chrome中使用Google字体的CSS规则对CSS规则失败
在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!
}
 


评论


CSS规则不区分大小写?

–sarkiroka
2015年1月18日14:38在

google.ru/search?q=CSS+区分大小写-> w3.org/TR/CSS2/syndata.html#characters“所有CSS语法在ASCII范围内都是不区分大小写的(即[az]和[AZ]等效),但不受CSS控制的部分除外。”

–ornic
15年1月18日在19:11



#4 楼

您可以按以下方式在文档样式表中编辑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> 




#5 楼

遗憾的是,使用JS编辑样式表的API在浏览器之间不一致。 YUI样式表实用程序会尝试消除这些差异,因此您可以使用它。如果您不想使用YUI本身,也可以查看源代码以了解其工作原理。

评论


这仍然有效吗?

– fiatjaf
16年4月12日在0:05

它在网站上说“已弃用”和“请勿将其用于新项目”,所以我最好的猜测是不会。

– stinodes
16年4月29日在6:30

#6 楼

根据您要实现的目标,更好的解决方案可能是将类更改/添加到包含元素(主体会这样做!),并相应地定义类。

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


,那么您只需使用

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


(或您选择的js框架的包装器),以更改yourclass元素内部的类wrapper的所有内容。

评论


针对您的括号:是的,有一种方法可以明确指定代码语言(meta.stackexchange.com/questions/63800/…)

– Briilliand
2014年2月14日在21:33



#7 楼

给您的样式标签一个ID,例如<style id="ssID">
如果有人为您制作样式,
告诉别人给样式标签一个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];

}


现在您有了样式表中所有内容的哈希表-
请注意,某些值将是未定义的,但不适用于
您关心的任何事情

,例如,如果您有一个名为#menuItem
的类,并且想要将其颜色更改为黑色,请执行这

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


该行将设置规则样式的颜色
在哈希表(cssHash)中查找其索引的颜色
更重要的是,您可能有几个不同的
类,您想一次更改所有的
类,就像您在大学换专业时的类一样


br />
假设您有四个不同的类
,并且您想要设置其所有背景d颜色
具有与某些用户从输入中选择的值相同的值

颜色选择器标签是<input id="bColor" type="color">
,要更改的类规则称为
#menuItem .homeAddr跨度和#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's value
    cssHash[obj].style.backgroundColor = bColor.value;

  });

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


评论


只是通过而已,但是大多数时候,这里的人们在代码上方发布解释,而不是在代码中添加注释。您可能希望将来考虑这样做。

– Peter G
17年4月22日在6:10

这是一个非常有用的想法,但请记住,ss0.sheet.rules可能具有键为“ length”的元素,甚至可能取决于浏览器等而具有“ item”。

–阿苏
17年5月16日13:00

#8 楼

尽管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 ) )


使用一些正则表达式,但是您将拥有在这种情况下可以转义特殊字符。

评论


关于答案的最后一部分,我认为应该使用match以外的方式来以任意顺序说明多个类名。例如,“ foo bar” .match(“ foo bar”)将返回“ foo bar”,但是“ foo bar” .match(“ bar foo”)将返回null。也许用空格分割并在for循环中检查所有类名将起作用(但是,前导/尾随空格应忽略,并注意不要从某个地方的多余空间中获取数组中的空字符串)。参考:W3语义

–追逐
2012年2月6日下午6:13