Override 'on the fly' css rules selectors of a css file with javascript

Viewed 114

I have a page containing a select tag that allow to change the css theme of the page "on the fly" with some javascript.

Now, I want to allow to change the css style for specifics html elements in the page.

By example, I have theses two 'theme' stylesheets :

/* in red theme file 'theme_red.css' */
.title{color:red;}
.text{...}
/* in blue theme file 'theme_blue.css' */
.title{color:blue;}
.text{...}

And I have some "select" tag "change theme" in the page. This is here a minimalist example, in a real case, the number of 'themable' html elements and the number of stylesheet are modular.

I'm looking for create a javascript function like this : (pure javascript ES6)

loadCssThemeFileOnTheFlyForSpecificHtmlElement(idOfSpecificHtmlElement, themeName){
    // 1) Insert a new link tag in the head of the page with href attribute "themeName + '.css'"
    ...

    // 2) for each css rules selector (of the css file ?), override the css selector rule like this : 
    // `.selector1` become `#idOfElement .selector1`
    // `.selector2` become `#idOfElement .selector2`
    // ...
    // `.selectorN` become `#idOfElement .selectorN`

}

And I'm stuck in the step 2 of the function insertCssFileOnTheFly. Is it possible to do what I want to do with some javascript ? I mean, is it possible to loop of the css rule of the current page and add to each selector rule the string "#idOfElement " ?

Thanks for any help

2 Answers

CSS can be removed or added on the fly using the document.head.removeChild() and document.head.appendChild() methods.

To remove an existing css file on the fly:

var redTheme = document.getElementById('red-theme-css')
document.head.removeChild(redTheme)

To add a new css file on the fly:

var blueTheme = document.createElement('link')
blueTheme.id = "blue-theme-css"
blueTheme.type = "text/css"
blueTheme.rel = "stylesheet"
blueTheme.href = "link-to-blue-theme-css-file"
document.head.appendChild(blueTheme)

The above method can be used either to change theme for the entire document, or for a specific component.

If the requirement is to change styling for only one component, then the css file to be loaded must be written in such a way that it has the classes that apply to the specific component only.

More information:

https://www.w3.org/wiki/Dynamic_style_-_manipulating_CSS_with_JavaScript

Is it possible to do what I want to do with some javascript ? I mean, is it possible to loop of the css rule of the current page and add to each selector rule the string "#idOfElement "?

Yes. Using javascript you can access and modify the contents of your stylesheets. For instance, if you have only one StyleSheet, you can reference it like this:

document.styleSheets[0]

Each StyleSheet has a CSSRuleList - an array-like object containing an ordered collection of CSSRule objects:

document.styleSheets[0].cssRules

And each CSSRule has, amongst its properties, a selectorText property.

So, if you want to reference the selectorText of the first CSSRule of your first StyleSheet, you can use:

document.styleSheets[0].cssRules[0].selectorText // .selector1

Working Example:

const myCSSRules = document.styleSheets[0].cssRules;

for (let CSSRule of myCSSRules) {

  CSSRule.selectorText = '#my-element ' + CSSRule.selectorText;
  console.log(CSSRule.selectorText);

}
.selector1 {
  color: red;
  font-weight: 700;
}

.selector2 {
  color: blue;
  font-weight: 700;
}
<p class="selector1">Selector 1</p>
<p class="selector2">Selector 2</p>

<div style="border: 1px dashed red; text-align:center;" id="my-element">
  <p class="selector1">Selector 1</p>
  <p class="selector2">Selector 2</p>
</div>


Further Reading:

Related