从 Javascript 更改 CSS 规则集

Posted

技术标签:

【中文标题】从 Javascript 更改 CSS 规则集【英文标题】:Changing a CSS rule-set from Javascript 【发布时间】:2010-11-27 09:50:55 【问题描述】:

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

这个特定的 CSS 规则集应用于页面上的许多元素(通过类选择器),我想在用户单击小部件时对其进行修改,以便所有元素都具有 类强>改变。

【问题讨论】:

查看一些答案,您的问题的含义似乎有些混乱。不存在“CSS 类”这一事实无济于事,但通常以这种方式错误描述了两种不同的事物。一个是“一个 html 类”,但我认为您指的是另一个 - CSS 规则集(在这种情况下,带有一个类选择器)。 我的意思是为类选择器设置 CSS 规则 相关 - Setting CSS pseudo-class rules from javascript 【参考方案1】:

可以,但是比较麻烦。如何做到这一点的最佳参考是以下文章:Totally Pwn CSS with Javascript (web archive link)。

我设法让它与 Firefox 和 IE 一起工作 - 我不能在 Chrome 中,虽然它似乎支持 DOM 方法。ricosrealm 报告说它也可以在 Chrome 中工作.

【讨论】:

以下是来自 MDC 的一些参考资料:developer.mozilla.org/en/DOM/document.styleSheetsdeveloper.mozilla.org/En/DOM/Stylesheet 在 Chrome 11 中测试。效果很好。 那个指南太棒了!!!我已经在最新的 Firefox 和 Chrome 上测试过它,它就像一个魅力!!! 链接已损坏(数据库已关闭),但看起来像someone turned it into a library。 这个答案已经过时了。查看现代解决方案here【参考方案2】:

虽然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 Semantics【参考方案3】:

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

.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/…)【参考方案4】:

遗憾的是,用于使用 JS 编辑样式表的 API 在浏览器中并不一致。 YUI Stylesheet Utility 试图消除这些差异,以便您可以使用它。如果您不想使用 YUI 本身,也可以查看 the source code 以了解它是如何工作的。

【讨论】:

这仍然有效吗? 网站上写着“已弃用”和“不要将其用于新项目”,所以我最好的猜测是没有。【参考方案5】:

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

    它在 Chrome 中使用 Google 字体的 CSS 规则失败 FireFox 安全检查失败

所以我稍微改变了它,但删除了delete 功能,因为我不需要它。已在 IE 11、FireFox 32、Chrome 37 和 Opera 26 中检查。

function getCs-s-rule(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 规则不区分大小写? google.ru/search?q=CSS+case+sensitive -> w3.org/TR/CSS2/syndata.html#characters "所有 CSS 语法在 ASCII 范围内都不区分大小写(即 [az] 和 [AZ] 是等效的),除了不在控制 CSS。”【参考方案6】:

这是一个基于 Totally Pwn CSS 和 Javascript 的现代版本。这是 ES6,我希望不要介意。

function getCs-s-rule(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 = getCs-s-rule('#header');
header.style.backgroundColor = 'red';

document.styleSheets 列出 CSSStylesSheets 对象的引用。访问页面中特定 sytleSheet 的其他方法是通过将 id 分配给 html 代码中的 stylelink 元素,并获取它在 javascript 中使用 document.getElementById('my-style').sheet。这是一些有用的方法:

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

主要浏览器,火狐?和 IE9+: setProperty()。

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

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

【讨论】:

这很好用!我只是在调用 find 之前添加检查 styleSheet.cssRules 的存在。【参考方案7】:

给你的风格标签一个ID,比如&lt;style id="ssID"&gt; 如果有人正在为你制作你的风格 告诉那个人给样式标签一个 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”

更重要的是,您可能有几种不同的 您想一次全部更改的课程 有点像你在大学转专业的时候

假设你有四个不同的类 你想设置他们所有的背景颜色 到相同的值,一些用户从输入中选择

颜色选择器标签是&lt;input id="bColor" type="color"&gt; 并且您要更改的课程规则被称为 #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's value
    cssHash[obj].style.backgroundColor = bColor.value;

  );

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

【讨论】:

只是路过,但大多数时候这里的人们将解释发布在他们的代码上方,而不是像 cmets 那样混入代码中。您将来可能会考虑这样做。 这是一个非常有用的想法,但请记住,ss0.sheet.rules 可能有一个带有“length”键的元素,甚至可能有“item”,具体取决于浏览器等。跨度> 【参考方案8】:

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

【讨论】:

以上是关于从 Javascript 更改 CSS 规则集的主要内容,如果未能解决你的问题,请参考以下文章

哪个 JavaScript 框架可以搜索 CSS 样式表规则并编辑它们的属性?

css阶段总结

从javascript更改css类[重复]

JavaScript从入门到精通第一课

从webkit内核简单看css样式和css规则优先级(权重)

获取代码中使用的所有 CSS 类选择器,这些选择器没有定义 CSS 规则集 [关闭]