demo · v130

CSSOM mutate bare-declaration blocks

The companion demo proves source-order semantics at render time. This one proves the underlying CSSOM contract: bare declarations after a nested rule live in a real CSSNestedDeclarations rule that you can iterate, insert, mutate, and delete from script — like any other CSSOM rule. Click the buttons to programmatically add and remove bare-declaration blocks and watch the rendered card update.

CSSOM rule tree of .card


      

live preview

.card with .icon
action:

the code

// Build a sheet adoptively so we own the rules.
const sheet = new CSSStyleSheet();
sheet.replaceSync(`
  .card {
    color: black;
    background: white;
    & .icon { color: blue; }
  }
`);
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];

const cardRule = sheet.cssRules[0]; // CSSStyleRule for .card

// Append a bare-declaration block AFTER the nested rule.
// The parser wraps it in a CSSNestedDeclarations rule on its own.
cardRule.insertRule("background: gold;", cardRule.cssRules.length);

// Iterate — the new rule is visible as its own entry.
for (const r of cardRule.cssRules) {
  console.log(r.constructor.name, "→", r.cssText);
}

// Delete the bare-declaration block by index.
cardRule.deleteRule(cardRule.cssRules.length - 1);

// Mutate in place — the .style object behaves like any CSSStyleRule's.
const bareBlock = [...cardRule.cssRules].find((r) =>
  r.constructor.name === "CSSNestedDeclarations"
);
if (bareBlock) bareBlock.style.setProperty("border", "3px dashed black");

see also