代码之家  ›  专栏  ›  技术社区  ›  tacoshy

为什么用新规则更新我现有的CSSStyleSheet没有效果?

  •  1
  • tacoshy  · 技术社区  · 2 月前

    我在用 new CSSStyleSheet() 为特定文档创建自定义样式表,其中样式取决于内容。
    在该样式表中,我使用根选择器添加CSS变量。然后,项目中的元素将通过ID进行选择,并获得使用这些变量的特定规则。问题是,我以前不知道ID,因此必须动态创建样式和选择器。
    到目前为止,它运行得非常完美。

    我现在面临的问题是,在某些特定事件中,CSS变量的值应该会发生变化。我试着用 insertRule() 有和没有索引。我也试过了 replace() replaceSync() 没有什么能达到预期的结果。

    现在的问题是,我该如何改变 root 对于这个样式表?

    const CSS = new CSSStyleSheet();
    
    const rootRule = `:root{
      --background: red;
    }`;
    CSS.insertRule(rootRule, 0);
    
    const bodyRule = `body { 
      background: var(--background); 
    }`
    CSS.insertRule(bodyRule, 1);
    
    document.adoptedStyleSheets = [CSS];
    
    
    // change color
    BUTTON.addEventListener('click', function() {
      console.log('button clicked');
      const newRule = `:root {
        --background: blue;
      }`
      CSS.insertRule(newRule, 0);
    })
    <button id="BUTTON">Change background-color</button>
    2 回复  |  直到 2 月前
        1
  •  2
  •   Rory McCrossan    2 月前

    这个问题是由于特殊性造成的。新的 --background: blue 规则正在应用,但已被现有规则覆盖:

    enter image description here

    解决这个问题的快速而肮脏的方法是使用 !important ,尽管这并不理想:

    const newRule = `:root {
      --background: blue !important;
    }
    

    更好的做法是在添加新规则之前删除原有规则。这可以使用 deleteRule() 。这是一个工作示例:

    const CSS = new CSSStyleSheet();
    
    const rootRule = `:root{
      --background: red;
    }`;
    CSS.insertRule(rootRule, 0);
    
    const bodyRule = `body { 
      background: var(--background); 
    }`
    CSS.insertRule(bodyRule, 1);
    document.adoptedStyleSheets = [CSS];
    
    
    BUTTON.addEventListener('click', function() {
      CSS.deleteRule(0); // delete the original :root rule
      
      const newRule = `:root {
        --background: blue;
      }`
      CSS.insertRule(newRule, 0);
    })
    <button id="BUTTON">Change background-color</button>
        2
  •  2
  •   TylerH    2 月前

    您正确地将规则插入到CSSStyleSheet中(您可以通过添加 console.log(CSS.cssRules[0].cssText); 点击按钮检查是否插入)。您遇到的问题是,您的代码被插入到索引处 0 ,意思 之前 您现有的 rootRule 。这是默认位置,但您也可以使用指定 CSS.insertRule(newRule, 0); 。由于CSS中特定选择器的规则会被相同选择器的后续规则覆盖 rootRule 仍然是被申请的。

    更改为 CSS.insertRule(newRule, 2); 你会看到它工作:

    const CSS = new CSSStyleSheet();
    
    const rootRule = `:root{
      --background: red;
    }`;
    CSS.insertRule(rootRule, 0);
    
    const bodyRule = `body { 
      background: var(--background); 
    }`
    CSS.insertRule(bodyRule, 1);
    
    document.adoptedStyleSheets = [CSS];
    
    
    // change color
    BUTTON.addEventListener('click', function() {
      console.log('button clicked');
      const newRule = `:root {
        --background: blue;
      }`
      CSS.insertRule(newRule, 2);
    })
    <button id="BUTTON">Change background-color</button>