Set CSS styles with javascript
Eugene Karataev

Eugene Karataev @karataev

About: undefined is not a function

Location:
Russia, Novosibirsk
Joined:
Apr 15, 2019

Set CSS styles with javascript

Publish Date: Apr 23 '19
126 18

Let's say you have a paragraph.



<p id="target">rainbow 🌈</p>


Enter fullscreen mode Exit fullscreen mode

And you need to change it's color with JS. What options do you have?

1. Inline styles

The most straightforward path. Query the element from DOM and change it's inline styles.



document.getElementById('target').style.color = 'tomato';


Enter fullscreen mode Exit fullscreen mode

inline styles

Short and simple.

2. Global styles

Another option is to create <style> tag, fill it with CSS rules and append the tag to the DOM.



  var style = document.createElement('style');
  style.innerHTML = `
  #target {
  color: blueviolet;
  }
  `;
  document.head.appendChild(style);


Enter fullscreen mode Exit fullscreen mode

global styles

3. CSSOM insertRule

Third option is less known. We gonna use CSSStyleSheet insertRule method.



  var style = document.createElement('style');
  document.head.appendChild(style);
  style.sheet.insertRule('#target {color: darkseagreen}');


Enter fullscreen mode Exit fullscreen mode

While it might look similar to the 2nd option, it's definitely different.
insertRule

As you can see in Chrome devtools, <style> tag is empty, but the style (darkseagreen color) is applied to the element. Also the color can't be changed via devtools because Chrome doesn't allow editing dynamic CSS styles.

Actually such behavior was the motivation to write this post. A popular CSS-in-JS library Styled Components use this feature to inject styles in production mode because of performance. This feature might be undesirable in specific projects or environments and some folks complain about it in the project's issues.

4. Constructable Stylesheets (July 2019 update)

It's now possible to create CSSStyleSheet object from JavaScript.



// Create our shared stylesheet:
const sheet = new CSSStyleSheet();
sheet.replaceSync('#target {color: darkseagreen}');

// Apply the stylesheet to a document:
document.adoptedStyleSheets = [sheet];


Enter fullscreen mode Exit fullscreen mode

More details are here.
This option is only valid for Chrome, so use with caution.

Do you know other options to add styles with javascript? What is your preferred option these days?

Thanks for reading!

Comments 18 total

  • freq32
    freq32Jun 24, 2019

    3 veeery interesting. thanks for the tip ;)

  • Ardalan
    ArdalanAug 16, 2019

    really great post i like it

  • Nagarjun
    NagarjunApr 18, 2020

    this is really helpful :)

  • marcin93
    marcin93May 26, 2020

    It's something I'm looking for. Thanks a lot!

  • Ardalan
    ArdalanJun 1, 2020

    great

  • Ardalan
    ArdalanJun 1, 2020

    hey can you maybe help me ?
    I have some things like this and I just want to Update the hidden class but I Update Complete Style

    <style id="style">
        .hidden{
             animation-name: bgshower;
            animation-duration: 2s;
            position: absolute;
            z-index: 2;
        }
        .neopa{
            background-color: darkred;
            font-size: large;
        }
    </style>
    
    Enter fullscreen mode Exit fullscreen mode

    var style = document.getElementById('style');
    var counter = parseInt(60);

            style.innerHTML = `
    
            .bghidden {
                height: 100%;
                width: 100%;
                background-color: #E96565;
                top: 0;
                left: 0;
                `+ 'animation-duration:' + counter + "s" + `;
    
                animation-name: bgshower;
                animation-delay: 0s;
    
                position: absolute;
                z-index: 2;
            }
            `;
            document.adoptedStyleSheets = [style];
    
    Enter fullscreen mode Exit fullscreen mode
    • Eugene Karataev
      Eugene KarataevJun 1, 2020

      I'm not 100% sure what you're trying to achieve, but if you need to add animations on an element(s) with JS after some event, consider the following way:

      • Define styles with css like
      .hidden {
      ...
      }
      
      .animate {
      ...
      }
      
      Enter fullscreen mode Exit fullscreen mode
      • Add/remove CSS classes with animations when necessary with DOM API: document.querySelectorAll('.hidden').classList.add('animate')
      • Ardalan
        ArdalanJun 1, 2020

        Thanks for writing but I just wanted to update an element's CSS with JS.
        no more new class I wanted to Edit animation-duration value from JS.
        I resolve it thx

  • Jooyoung Moon
    Jooyoung MoonJun 8, 2020

    Hi :D
    I just wondered if using insertRule for performance or not and I found this article. Thanks !

    But how it differ?

    • Eugene Karataev
      Eugene KarataevJun 8, 2020

      I don't think you ever need to use insertRule in your day-to-day job unless you hit some performance bottleneck when working with styles.
      I think optimizations with insertRule are useful for libraries (like styled-components), but add unnecessary complexity when developing regular websites or apps.

  • yellow1912
    yellow1912Jun 28, 2020

    With CSSStyleSheet, what is the best way to replace a rule? I see insertRule seems to take an index, if I re-use that same index then that rule will be replaced? The reason is that I want to allow the endusers to change some styles via a UI, then quickly update that to the specific element.

    • xgqfrms
      xgqfrmsSep 4, 2020

      style.setContent bug ❌

          const style = document.createElement(`style`);
          // this.shadowRoot.appendChild(this.templateContent);
          // log(`this.shadowRoot`, this.shadowRoot);
          style.setContent = `
            .run {
              width: 100px;
              height: 100px;
              background: url(https://www.boston.com/wp-content/uploads/2016/05/yuge_anger.png) 0 0;
              animation: run 500 step(6) infinite;
            }
            @keyframes run {
              from {
                background-position: 0 0;
              }
              to {
                background-position: -600px 0;
              }
            }
          `;
      
      
  • Zouhair Sahtout
    Zouhair SahtoutDec 16, 2023

    Thanks man for sharing, I was looking for something like this long ago

Add comment