Styling Elements in JavaScript

Reduce reflows, organize styles.


There's a few ways of styling elements in JavaScript.

1. JavaScript Style Method

    document.getElementById('header1').style.border = '1px solid red';
    

*click the boxes

    document.getElementById('header1').style.textTransform = 'uppercase';
    

This is very common. It's easy to use, descriptive, and it's the proper use of the style method.

This way of controling styles is very easy to overlook, harder to debug and can make big impacts in performance.

Reflows

We can't avoid reflows, but we can reduce them.

When we make changes to the DOM, those changes need to recalcuate the styles and other attributes associated with each affected element.

These changes are lightning fast but if not managed can bog down your application.

    var container = document.getElementById('example2');
    var new_header = document.createElement('h4');

    // Append the header to the container element
    container.appendChild(new_header);

    // Header Information - Each of these will cause a reflow
    new_header.innerHTML = 'This will trigger 4 more reflows then it needs to.';
    new_header.style.padding = '5px 10px';
    new_header.style.background = 'red';
    new_header.style.color = 'white';
    

This is a subtle but important difference.

    var container = document.getElementById('example3');
    var new_header = document.createElement('h4');

    // Header Information - Only 1 reflow from appending the element
    new_header.innerHTML = 'This header is only appended after all the styles are set.';
    new_header.style.background = 'green';
    new_header.style.padding = '5px 10px';
    new_header.style.color = 'white';

    // Append the header to the container element AFTER all the styles are set
    container.appendChild(new_header);
    

Before the element exists, it will not trigger reflows. Adding all of the styles and attributes before appending the element is a big optimization.


Class

The fastest way to style elements in JavaScript is leveraging the power of CSS, and only appending a class to manage all those styles.

    var container = document.getElementById('example4');
    var new_header = document.createElement('h4');

    // Header Information
    new_header.setAttribute('class', 'cool-header');
    new_header.innerHTML = 'This header has styles from CSS.';

    // Append the header to the container element
    container.appendChild(new_header);
    

Great, but I don't want to have to serve a CSS file with my JavaScript.

We don't have to. And we can organize the styles a lot better.


Style Config and Tag

You're going to thank yourself later for this, and so will your developer friends

    // Create a style element we can append to the head
    var module_styles = document.createElement('style');

    // Using an array, we can write our styles much like we would in a CSS file
    var styles_config = [

    '#example5{',
      'background: green;',
    '}',

    '.COOLER-header{',
      'padding: 5px 10px;',
      'color: #222;',
      'background: orange;',
    '}'

    ].join(''); // Turns the array into a string

    // Populate and append style tag
    module_styles.innerHTML = styles_config;
    document.getElementsByTagName('head')[0].appendChild(module_styles);



    // Now let's continue our application like normal.
    var container = document.getElementById('example5');
    var new_header = document.createElement('h4');


    // Header Information
    new_header.setAttribute('class', 'COOLER-header');
    new_header.innerHTML = 'This header has styles from an inline style tag appended to the head.';

    // Append the header to the container element
    container.appendChild(new_header);
    

For this example in particular, it seems like a lot of code but it's worth the setup.

In larger applications the benefits of this pattern are more obvious.

  1. One location for all the styles. No searching required.
  2. Limit reflows from careless style methods.
  3. Removes the need for style specific methods or functions.
  4. No additional HTTP request, the style tag is dynamically added when the JavaScript is loaded. If your JavaScript was inline, no HTTP request would be made.

One important note

Inline JavaScript and CSS cannot be cached by the browser. Depending on the scale of your application, loading CSS dynamically like this could be less performant than a one time http request that is then cached.