How does CSS works behind the scenes?

How does CSS works behind the scenes?

How does CSS actually work?

When a user opens the page in the browser, the browser performs the following steps before rendering the web page -

  1. Loads the initial HTML file
  2. Takes loaded HTML code and parses it, which basically means it decodes the code line by line
  3. Then the browser builds the DOM (Document Object Model)
  4. As the browser parses HTML it also finds the style sheets included in the HTML head. CSS is also parsed, but the parsing of CSS is a bit more complex and there are two main steps

    1. Conflicting CSS declarations are resolved through a process known as the cascade
    2. The second step is to process final CSS values
  5. The final CSS is also stored in a tree-like structure called the CSS Object Model (CSSOM)

  6. After the HTML and CSS are parsed and stored, these together form render tree

  7. In order to render the page, the browser uses the algorithm called visual formatting model. this algorithm calculates and uses a bunch of stuff like the box model, floats, and positioning.

  8. After the visual formatting model has done its work, the website is finally rendered.

CSS-work.drawio  (2).png

Diagram Credit - Jonas Schmedtmann

What is cascade in CSS?

We have seen that parsing of CSS includes two-phase let's take a look at the first phase which is Resolve conflicting CSS declarations (cascade). cascade is a process of combining different stylesheets and resolving conflict between different CSS rules and declarations when more than one rule applies to a certain element.

CSS rule - css-basics.png

Now CSS can also come from different sources. the most common one is the CSS that we the developers write, and these declarations are called Author declarations. another CSS that is coming from the user is called User declarations. for instance when the user changes the default font size in the browser then that is User CSS. and there are the default browser declarations which is called Browser (user agent) CSS.

How does the cascade actually resolve conflicts when more than one rule applies?

cascade first looks at the importance, at the selector specificity, and the source order of conflicting declarations in order to determine which one takes precedence.

css-specificity..png Diagram Credit - Jonas Schmedtmann

1. IMPORTANCE

There is a special piece of CSS that you can use to overrule all of the above calculations. However, you should be very careful with using it — !important. This is used to make a particular property and value the most specific thing, thus overriding the normal rules of the cascade.

In the below code snippet the background color of span in themake-pink class is declared with !important so it has more specificity than the background color declared in the span declaration block.

<span class="make-pink">Rule everything with one selector.</span>
span {
  background-color: rgb(250, 20, 231);
  font-size: 2rem;
  color: white;
}

.make-pink {
  background-color: pink !important;
  font-size: 2rem;
  color: white;
}

2. SPECIFICITY

Once you understand the fact that source order matters, at some point you will run into a situation where you know that a rule comes later in the stylesheet, but an earlier, conflicting, rule is applied. This is because that earlier rule has a higher specificity — it is more specific, and therefore is being chosen by the browser as the one that should style the element.

Inline styles have the highest specificity then followed by IDs, then classes and pseudo-classes and attribute selectors, and finally the least specific element and pseudo-element selector.

The specificity is actually not just one number, but one number for each of the four categories ie (Inline styles, IDs, classes, pseudo-elements and attribute, elements). for each of these, we count the number of occurrences in the selector.

specificitydraw.png

we start to look at the numbers from left to right starting with the most specific category, the inline styles. if there is a selector with 1 it wins against all the selectors because this is the most specific category. but in the above code, this is not the case. so let's move on to the IDs we see that selector 2 has 1 here. so the winner is the selector 2 because it's the most specific selector of all.

The universal selector * has no specific value (0, 0, 0, 0)

3. SOURCE ORDER

In source order, if all the declarations selectors have the same specificity then simply the last declaration that will be used to style the selected element.

Processing the final CSS values

This is the final step of parsing CSS. point to remember the default font size of the content on a webpage is always 16px, but you can change it at any point in time. Also, we should never set the font size in pixels. it's bad practice and a bad user experience. we should always use a rem (1rem = 16px). and processing final values includes multiple steps -

Declared values - These values are declared by the author when writing a document like a developer declared a font size for the heading is font-size : 2rem. this is called an author value.

Cascaded values - The cascade value represents the result of the cascade. consider the below code snippet we declared the font size of the paragraph in p tag and .main class and here is a conflict. for resolving this we will use cascade which we have seen above. we know classes have more precedence than elements so the font size for paragraph 2rem will be applied.

<p class="main">Hello there!</p>
p{
  font-size: 1.5rem;
 }
.main{
 font-size: 2rem;
}

Specified values - The specified values is the value that the author declared inside the style sheet. most of the times specified values are the cascade values. if there are no cascade values then the specified value has defaulted.

Computed values - In this relative values like ('em', 'ex', 'vh', 'vw') is converted into absolute value.

Used values - The used values is the result of taking the computed value and calculating if there are any relative values is remaining.

Actual value - A used value is in principle ready to be used, but a user agent may not be able to make use of the value in a given environment. the actual value is the used value after any browser adjustments.

Inheritance

In simple terms, Inheritance is something passed down from your parents to you. In CSS, inheritance controls what happens when no value is specified for a property on an element. and it's categorized into two types:

  • inherited properties
  • non-inherited properties
  1. Inherited properties

When we do not specify an inherited property on an element then the computed value of parent elements will be applied.

<h3>We are learning <b>inheritance</b> in CSS</h3>
h3{
color:pink;
}

the word "inheritance" will appear pink since the b elements have inherited the value of the color property from the h3 element.

  1. Non-inherited properties

When no value for a non-inherited property has been specified on an element, the element gets the initial value of that property.

<h3>We are learning <b>inheritance</b> in CSS</h3>
h3{
border: medium solid;
}

the words "inheritance" will not have a border (since the initial value of border-style is none).

Well now both HTML and CSS have been parsed and stored into their object models, they both form the Render Tree. It’s formed with a combination of HTML, DOM, and CSSDOM. It’s used to calculate the layout of each element on the page and helps render the page.

After the render tree has been formed, the website uses something known as the Visual Formatting model, which we can see in the first figure. A Visual Formatting model is an algorithm that calculates the boxes and the box sizes for each element on the webpage and helps lay those elements on the page to determine the final layout of the page.

Conclusion

The main focus of this blog is to introduce you to how CSS works behind the scenes. one point to note is that !important has the highest precedence and we should use rem units instead of pixels. by assigning rem units to root elements we can control every other element easily.


Thank you for reading. 🙏

If you enjoyed this article or found it helpful, give it a thumbs-up. 👍

Content Credit - Jonas Schmedtmann, MDN Web Docs

Let's Connect. 👋

Github | LinkedIn | Twitter