Styles and Classes

In this chapter, we are going to show you how to alter the DOM by modifying styles and classes.

But, before getting into the JavaScript ways of modifying styles and classes let’s check out an important rule. In general, there exist two ways of styling an element:

  1. Creating a class in CSS, as well as adding it <div class="...">.
  2. Writing properties directly into style: <div style="...">.

As it was mentioned above, JavaScript is also capable of modifying both style properties and classes. However, CSS is always preferable for styling. For instance, style can be acceptable in case you calculate coordinates of an element dynamically and wish to set them from JavaScript, as follows:

let top = /* complex calculations */ ;
let left = /* complex calculations */ ;

elem.style.left = left; // e.g '100px', calculated at run-time
elem.style.top = top; // e.g '400px'

For making the text blue, adding a background icon, you need to describe it in CSS, then add the class. It’s quite flexible and easier to support.

Modifying Classes

So, the style attribute corresponds to the style selectors of CSS. It is not to be confused with ES6 classes: a unique type of JavaScript function.

The CSS classes are used for applying styles to multiple elements, except ID that can only exist once a page. In JavaScript, there are className and classList properties for working with the class attribute.

className and classList

One of the most used actions in scripts is changing a class. Earlier there was a limitation in JavaScript: a reserved word, such as “class” couldn’t be considered an object property. Nowadays, there is no such limitation.So, the property “classname” was introduced: the elem.className matches the “class” attribute.

The example will look as follows:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
  </head>
  <body class="main classes">
    <script>
      alert(document.body.className); // main classes
    </script>
  </body>
</html>

In the event of assigning something to elem.className, it can replace the whole string of classes. Sometimes, it can be what you need, but, frequently, you may want to add or remove a single class. For that, you can use the property of elem.classList. The elem.classList is a unique object with methods of adding, removing or toggling a single class. For example:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
  </head>
  <body class="main classes">
    <script>
      // add a class
      document.body.classList.add('classList');
      alert(document.body.className); // main classes classList
    </script>
  </body>
</html>

So, you can work both on the full class string using className or on individual classes with classList. You can choose it depending on your needs.

Let’s check out the methods of classList:

  • For adding or removing the class, the elem.classList.add/remove("class") method is used.
  • For adding the class that doesn’t exist, the elem.classList.toggle("class") method is used. If it already exists, with this method, you can remove it.
  • The method elem.classList.contains("class") checks for a particular class, returning true or false.

Also, the classlist is iterable: you can list all classes with for..of, like here:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
  </head>
  <body class="main classes">
    <script>
      for(let name of document.body.classList) {
        alert(name); // main, and then classes
      }
    </script>
  </body>
</html>

Element Style

The elem.style property is an object that matches with what is written in the “style” attribute. Setting elem.style.width="100px is similar to having in the attribute style a string width:100px.

The camelCase is used for the multi-word property, as follows:

background-color => elem.style.backgroundColor

z-index => elem.style.zIndex

border-left-width => elem.style.borderLeftWidth

Here is an example of a multi-word property:

document.body.style.backgroundColor = prompt('background color?', 'red');

Resetting the Style Property

Sometimes, you need to assign a style property and then to remove it. For example, for hiding an element, you can set elem.style.display = "none".

Later, you may want to remove the style.display, as if you have never set it. So, instead of delete elem.style.display, an empty string should be assigned to it: elem.style.display = "". Let’s check out an example:

// if we run this code, the <body> will blink
document.body.style.display = "none"; // hide
setTimeout(() => document.body.style.display = "", 2000); // back to normal

In case you set style.display to an empty string, the browser applies CSS classes, as well as its built-in styles regularly, as though there was no such style.display.

As a rule, you can use style.* for assigning individual style properties. It is not possible to set the whole style like div.style="color: red; width: 200px", as div.style is considered an object and is read-only.

A particular property, such as style.cssText, is used for setting a full style as a string, like this:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
  </head>
  <body>
    <div id="div">Box</div>
    <script>
      // we can set special style flags like "important" here
      div.style.cssText = `color: red !important;
        background-color: yellow;
        width: 200px;
        text-align: center;
      `;
      alert(div.style.cssText);
    </script>
  </body>
</html>

Anyway, this property is rarely used.

Mind the Units

It is essential to add CSS units to values. For example, you must not set elem.style.top to 20 but rather to 20px. In the opposite case, it will not work:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
  </head>
  <body>
    <script>
      // doesn't work!
      document.body.style.margin = 40;
      console.log(document.body.style.margin); // '' (empty string, the assignment is ignored)
      // now add the CSS unit (px) - and it works
      document.body.style.margin = '40px';
      alert(document.body.style.margin); // 40px      
      alert(document.body.style.marginTop); // 40px
      alert(document.body.style.marginLeft); // 40px
    </script>
  </body>
</html>

Please, take into account that the browser “unpacks” the style.margin property in the last lines, inferring style.marginLeft and style.marginTop from it.

Computed styles: getComputedStyle

Let’s learn how to read the style.

Imagine, you want to know the size, the margins or the color of an element. Note that the style property can operate only on the value of the “style” attribute, without any CSS cascade. Hence, elem.style will not help to read anything coming from CSS classes.

In the example below, style doesn’t see the margin:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
    <style>
      body {
        color: red;
        margin: 20px
      }
    </style>
  </head>
  <body>
    The red text
    <script>
      alert(document.body.style.color); // empty
      alert(document.body.style.marginTop); // empty
    </script>
  </body>
</html>

But, in case you need to increase the margin by 40px, you will need the current value of it. For that purpose, you can use the getComputedStyle method. The syntax of the getComputedStyle method is the following: getComputedStyle(element, [pseudo]).

In the syntax above, the element is the element to read the value for. And, the pseudo is a pseudo-element if required ( for example, ::before). Either no argument or an empty string means the element itself.

The result will be an object with styles, such as elem.style, with respect to the overall CSS classes, like here:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
    <style>
      body {
        color: red;
        margin: 20px
      }
    </style>
  </head>
  <body>
    <script>
      let computedStyle = getComputedStyle(document.body);
      // now we can read the margin and the color from it      
      alert(computedStyle.marginTop); // 20px
      alert(computedStyle.color); // rgb(255, 0, 0)
    </script>
  </body>
</html>

Computed and Resolved Values

In CSS, there are two concepts:

  1. The first one is a computed style value, which is the value after all CSS rules and CSS inheritance is applied, as the consequence of the CSS cascade. It may look like the following: height:1em or font-size:125%.
  2. The second one is the resolved style value: the one that is finally applied to the element. Values, such as 1em or 125% are similar to each other. The browser takes the computed value, making all the units fixed and absolute. For geometry properties, the resolved values can have a floating-point ( for example, width:50.5px).

Please, take into consideration that getComputedStyle requires the full property name. You need to always ask for the specific property you need (for instance, marginTop, paddingLeft orborderTopWidth). Otherwise, there are no guarantees to get the correct result.

Summary

In brief, we can conclude that there are two DOM properties for managing classes:

  • className: that is a string value, good for managing the whole set of classes.
  • classList: that is the object with the methods add/remove/contains/toggle, used generally for individual classes.
  • For changing the styles you can use the following properties:

  • The style property considered an object with camelCased sides. To read and to write to it is the same as modifying properties in the “style” attribute.
  • The style.cssText property matches the whole "style", the full string of styles.
  • The getComputedStyle(elem, [pseudo]) is targeted at returning the style-like object with them.



Do you find this helpful?

Related articles