skip to Main Content

I want to add a CSS rule to the DOM:

This is my code

function empty_rule(sheet, class_name) {
    const index = sheet.cssRules.length;
    sheet.insertRule(`.${class_name} { }`, index);
    return sheet.cssRules[index];
}

function make_style() {
  const $head = $('head');
  const $style = $('<style type="text/css"/>').appendTo($head);
  return $style.get(0).sheet;
}

function set_css(sheet, class_name, style) {
    const selector = `.${class_name}`;
    let rule = [...sheet.cssRules].find(rule => {
        return rule.selectorText === selector;
    });
    if (!rule) {
        rule = empty_rule(sheet, class_name);
    }
    Object.assign(rule.style, style);
}


const sheet = make_style();
const rule = empty_rule(sheet, 'cmd-terminal');

console.log(sheet);
console.log(rule);

/*
set_css(sheet, 'cmd-terminal', {
    color: 'red'
});
*/

On CodePen I’ve added this CSS to see the CSS:

style {
    display: block;
    white-space: pre;
    font-family: monospace;
}

But I don’t see any CSS added, I attempt to add the given CSS in the comments. But I don’t even see the empty rule. I was asking chatGPT but it gave no help in solving the issue.

Here is the CodePen link

I use the cash library (lightweight jQuery alternative).

I was trying to add display: block; to the empty rule (it was a chatGPT suggestion) but it didn’t solve the issue.

I even tried what is in MDN:

$('body style').get(0).sheet.insertRule("#blanc { color: white }", 0);

but the style didn’t change.

EDIT: I’ve added:

This HTML:

<p id="blanc">hello</p>

I have the same behavior in Firefox, Google Chrome, and Safari.

and the tag disappears when JavaScript runs. So the question is why The style is not updated in DOM (devTools) and why The style I’ve added doesn’t appear (when added display: block)?

Is it possible to update the DOM so you can debug the CSS more easily?

3

Answers


  1. Chosen as BEST ANSWER

    So it seems the cssRules are not visible in the DOM. But you can create debug code that will dump the CSS and add it back to the DOM:

    function dump_css(sheet) {
        return [...sheet.cssRules].map(rule => rule.cssText).join('n')
    }
    
    $('head style:last-child').text(dump_css(sheet));
    

    This will render dynamic CSS into the DOM. This code can be used while debugging.

    See this fork of the original CodePen demo.


  2. It seems you are expecting that modifying "virtual" sheet.CSSRules will be reflected back into HTMLStyleElement’s "innerHTML". But apparently, it will not:

    <style
     id=s
     contenteditable
     style="
      display: block;
      white-space: pre;
      border: inset;
    ">body {
     background-color: darkslategray;
     color: tan;
    }
    
    [onclick]:empty::after { content: attr(onclick); }
    </style>
    i:
    <input id=i value="body { color: red; }">
    <button onclick="
    s.sheet.insertRule(i.value, s.sheet.rules.length);
    "></button>

    This demonstrates that adding a new rule into sheet attached to style element has effect without changing original element’s content.

    Login or Signup to reply.
  3. In a web page, the Document Object Model (DOM) is not immediately updated to reflect changes made to a stylesheet by using the insertRule method to add new CSS rules. This can often confuse developers who assume that using insertRule to add a new CSS rule will change the page’s styling right away.

    This is because the CSS Object Model (CSSOM) provides the insertRule method, which functions at a lower level than the DOM. It doesn’t cause the page to automatically reflow or repaint; instead, it lets you programmatically add new CSS rules to a stylesheet. Stated differently, it prevents the browser from instantly recalculating the styles and updating the rendered output.

    Usually, you have to force a reflow or repaint of the page in order to observe the consequences of the newly inserted CSS rule. A DOM element’s class name can be changed, its inline style can be updated, or a layout change can be forced. Here’s an example of how to apply a recently added CSS rule to a particular JavaScript element:

    // Create a new CSS rule
    var stylesheet = document.styleSheets[0]; // Assuming the stylesheet you want to modify is the first one
    var rule = "p { color: red; }";
    stylesheet.insertRule(rule, 0); // Insert the rule at the beginning of the stylesheet
    
    // Apply the new CSS rule to a specific element
    var paragraph = document.querySelector("p"); // Select the desired paragraph element
    paragraph.style.color = "red"; // Update its inline style to trigger the change

    In this example, we edit the inline style of a particular p element to instantly apply the new style and include a new CSS rule to change the text color of all p elements to red.

    While insertRule enables dynamic stylesheet editing, it may only support a limited number of older browsers. As such, you should use caution while using it to prevent unexpected behavior. For updating the DOM and changing styles dynamically, classes and JavaScript are being used more frequently.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search