【问题标题】:Is it possible to alter a CSS stylesheet using JavaScript? (NOT the style of an object, but the stylesheet itself)是否可以使用 JavaScript 更改 CSS 样式表? (不是对象的样式,而是样式表本身)
【发布时间】:2011-10-01 00:20:12
【问题描述】:

是否可以使用 JavaScript 更改 CSS 样式表?

不是在谈论:

document.getElementById('id').style._____='.....';

上午谈论改变:

#id {
    param: value;
}

除了做一些肮脏的事情(顺便说一句,我们还没有尝试过),比如在头部创建一个新对象,innerHTML 在其中创建一个样式标签等。尽管这样,即使它确实有效,也会带来一些问题因为样式块已经在别处定义了,我不确定浏览器何时/是否会解析动态创建的样式块?

【问题讨论】:

  • 可能值得尝试在 JavaScript 中创建一个 <style> 元素,然后将其附加到 <head> 元素的末尾。我怀疑它会在附加后立即应用,就像 <link>to 样式表一样。可能比尝试编辑样式表本身更可靠。

标签: javascript html css stylesheet alter


【解决方案1】:

截至 2011 年

可以,但您将面临跨浏览器兼容性问题:

http://www.quirksmode.org/dom/changess.html

截至 2016 年

浏览器支持有了很大改进(支持所有浏览器,包括 IE9+)。

  • insertRule() 方法允许向样式表动态添加规则。

  • 使用deleteRule(),您可以从样式表中删除现有规则。

  • 可以通过样式表的cssRules 属性访问样式表中的规则。

【讨论】:

  • 讨厌它让我等待 11 分钟来正确回答这个问题。这正是我正在寻找的。谢谢。
  • 小心,那个页面已经有 4 年历史了,从那时起已经发生了很大的变化。例如在 Firefox 5 中,selectors of the rules according to your browser 显示为 0 = body
  • 链接现在似乎已损坏...任何人都可以编辑此答案并简要介绍在提供的链接中找到的内容吗? (注意:我在工作,所以网站可能刚刚被屏蔽,但无论哪种方式,如果可能,内容都应该在这里发布)。
  • @MathieuRodic 有效。我的工作网络似乎有问题。对于可能无法访问该链接的其他人,我仍然认为在答案中至少包含摘要级别的详细信息是个好主意,但这只是我的意见。
  • 这不再是真的。见my answer
【解决方案2】:

我们可以使用.insertRule.cssRules 的组合来一直做到这一点,回到IE9:

function changeStylesheetRule(stylesheet, selector, property, value) {
    // Make the strings lowercase
    selector = selector.toLowerCase();
    property = property.toLowerCase();
    value = value.toLowerCase();
    
    // Change it if it exists
    for(var i = 0; i < stylesheet.cssRules.length; i++) {
        var rule = stylesheet.cssRules[i];
        if(rule.selectorText === selector) {
            rule.style[property] = value;
            return;
        }
    }
  
    // Add it if it does not
    stylesheet.insertRule(selector + " { " + property + ": " + value + "; }", 0);
}

// Used like so:
changeStylesheetRule(s, "body", "color", "rebeccapurple");

Demo

【讨论】:

  • 如果您在使用旧浏览器时遇到问题,将 .cssRules 更改为 .rules 可能会有所帮助。 Chrome 也可以省略.insertRule 的第二个参数,但其他浏览器如 FF 需要它
  • 如果您的浏览器在修改样式时没有更新,您可以在重新添加之前删除该样式。为此,请更改 for 循环并添加 s.deleteRule(i) 并删除 return 语句。
  • 另外值得注意的是,由于是小写,backgroundPosition 等属性将不起作用。这也需要转换为它的连字符等效项 (background-position) 以与 insertRule() 一起使用。
  • 这不符合 OP 的预期。编辑后的规则分配给检查器中看到的
【解决方案3】:

当我想以编程方式向一个对象添加一堆样式时,我发现以编程方式向对象添加一个类更容易(这样的类在您的 CSS 中具有与之关联的样式)。您可以控制 CSS 中的优先顺序,以便新类中的新样式可以覆盖您之前的内容。这通常比直接修改样式表容易得多,并且可以完美地跨浏览器运行。

【讨论】:

  • 这是个好主意。今晚我们将测试各种做事方式,并将返回对我们最有效的方法:)
【解决方案4】:

更改样式规则中的属性

function change_css_style (titulo,selector,propiedad,valor) {        
        let i=0;
        while (i<document.styleSheets.length) {
            if (document.styleSheets[i].title==titulo) {
                let y=0;
                while (y<document.styleSheets[i].cssRules.length) {
                    if (document.styleSheets[i].cssRules[y].selectorText==selector) {                                               
                        document.styleSheets[i].cssRules[y].style[propiedad] = valor;                                                                       
                        y = document.styleSheets[i].cssRules.length;
                    } 
                    y++;
                }               
                i=document.styleSheets.length;
            } 
            i++;
        }

    }

演示

<style title="chat_inicio">
    .contenido .mensajes {
          width: 100px;
          height: 300px;    
    }
</style>

使用选择器 .contenido .mensajes 将标题为 chat_inicio 的样式书更改为 width 样式的属性为 475px

<script>
     cambiar_css_style ('chat_inicio','.contenido .mensajes','width','475px');
</script>

【讨论】:

    【解决方案5】:

    2020

    这种方法的一些优点:

    • 不需要(但允许)指定样式表。
    • 允许一次添加/修改多个样式
    • 接受!important 属性
    • 匹配 CSS 选择器时忽略多余的空格
    • 更改最后一个匹配现有规则,或附加到最后一个匹配样式表的末尾。 (其他答案添加/更改可能会被否决的第一条规则。)

    用法:

    adjustCSSRules('#myDiv', 'width: 300px !important');
    

    方法:

    function adjustCSSRules(selector, props, sheets){
    
        // get stylesheet(s)
        if (!sheets) sheets = [...document.styleSheets];
        else if (sheets.sup){    // sheets is a string
            let absoluteURL = new URL(sheets, document.baseURI).href;
            sheets = [...document.styleSheets].filter(i => i.href == absoluteURL);
            }
        else sheets = [sheets];  // sheets is a stylesheet
    
        // CSS (& HTML) reduce spaces in selector to one.
        selector = selector.replace(/\s+/g, ' ');
        const findRule = s => [...s.cssRules].reverse().find(i => i.selectorText == selector)
        let rule = sheets.map(findRule).filter(i=>i).pop()
    
        const propsArr = props.sup
            ? props.split(/\s*;\s*/).map(i => i.split(/\s*:\s*/)) // from string
            : Object.entries(props);                              // from Object
    
        if (rule) for (let [prop, val] of propsArr){
            // rule.style[prop] = val; is against the spec, and does not support !important.
            rule.style.setProperty(prop, ...val.split(/ *!(?=important)/));
            }
        else {
            sheet = sheets.pop();
            if (!props.sup) props = propsArr.reduce((str, [k, v]) => `${str}; ${k}: ${v}`, '');
            sheet.insertRule(`${selector} { ${props} }`, sheet.cssRules.length);
            }
        }
    

    Demo

    该方法接受三个参数:

    • 选择器 [String] - CSS 选择器 - 例如:'#myDiv'
      空格会自动减少(.myClass #myDiv 将匹配 .myClass #myDiv
    • 规则 [CSS 字符串,对象] - 例如(任何一个都可以接受):
      • { border: "solid 3px green", color: "white" }
      • 'border: solid 3px green; color: white'
    • 工作表(可选)[字符串,样式表]
      • 如果为空,将检查所有样式表
      • 'myStyles.css' 工作表的相对或绝对 URL
      • document.styleSheets[1] - 对工作表的引用

    其他例子:

    adjustCSSRules('#myDiv', {width: '30px'}); // all stylesheets
    adjustCSSRules('#myDiv', 'width: 30px', 'style.css'); // style.css only  
    adjustCSSRules('#myDiv  .myClass', 'width: 30px', document.styleSheets[0]); // only first stylesheet
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-31
      • 2010-12-04
      • 1970-01-01
      • 1970-01-01
      • 2011-12-05
      • 1970-01-01
      相关资源
      最近更新 更多