Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does updating my existing CSSStyleSheet with a new rule have no effect?

I'm using new CSSStyleSheet() to create a custom stylesheet for a specific document where the styles depend on the content.
Within that stylesheet, I add CSS variables with the root selector. Elements in the project will then be selected by an ID and get specific rules that use those variables. The issue is, that I do not know the IDs before, and as such the styles and the selectors have to be created dynamically.
So far it works flawlessly.

The issue that I facing now is that during some specific events, the value of the CSS variables should change. I tried changing it by using insertRule() with and without index. I also tried replace() and replaceSync(). Nothing achieved the desired result.

The question now is, how can I change the root for this stylesheet?

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>
like image 794
tacoshy Avatar asked Sep 02 '25 03:09

tacoshy


1 Answers

The issue is due to specificity. The new --background: blue rule is being applied, but it's overridden by the existing rule:

enter image description here

The quick and dirty fix to this would be to use !important, although this is not ideal:

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

A better aproach would be to remove the original rule, before adding the new one. This can be done using deleteRule(). Here's a working example:

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>
like image 99
Rory McCrossan Avatar answered Sep 04 '25 17:09

Rory McCrossan