Understanding CSS rendering issues
Tags: webdev, webperf, css
Published: 2020-11-21 10:02:35


Understanding how CSS renders is essential to prevent cumulative layout shift and jank.

It occurred to me that many developers assume that if a page has a weird rendering, it's because of shitty JavaScript or too many contents.  

While it's probably true in some cases, most of the time, CSS is the culprit.

CSS is render-blocking. The browser blocks the page render until all CSS rules are loaded. If you overuse expensive CSS properties, you might get weird visual effects like jank.

## What is jank?

The term "jank" describes a weird impression when browsing a website.

Does your page feel choppy? When the page loads or when scrolling, is there any unwanted motion on the screen?

If so, that's jank, but how does it happen?

Generally, devices refresh 60 times per second. Therefore you have to keep up with 60 frames per second for your rendering, which leaves only 16.66ms (1000ms/60 frames) to run CSS calculations.

If you use expensive CSS properties and animations, the browser has to recalculate positions and sometimes even redraw the entire page, which takes a lot of time. If it takes more than the 16.66ms allowed, the frame stays on the screen, the frame rate goes lower than the 60 FPS, and you get jank.

It's even less than 16.66ms as browsers do some stuff too in that time.

## CSS Triggers and Frame Budget

CSS rendering requires several steps:

1. It determines which CSS properties apply to which elements.
2. It builds the Layout with positions and dimensions.
3. It draws out colours, borders, images, and texts.
4. It orders all elements onto the screen.

All those layers come in that order and consecutively, so if your CSS rule triggers the second step, also called "Layout", it will trigger the third and last steps after. 

Ideally, you want your CSS only to trigger the last step, which is the less taxing of all steps. 

That is the reason why some CSS properties are more expensive than others. If you want to read more about CSS triggers, please check [csstriggers.com](https://csstriggers.com/).

## Repaint and DOM reflow

With CSS rendering steps in mind, it is a little easier to understand what CSS reflow and repaint are.

Repaints happen when the skin of elements change but not their layout (e.g., changing background-color). In contrast, reflows affect the layout, which forces the engine to recalculate positions and dimensions.

Reflows are even more expensive than repaints. It often causes the whole page to be re-rendered (children and ancestors nodes also reflow).

## Cumulative layout shift

Cumulative layout shift is one of the core web vitals that Google will add as a ranking factor in the next months. This user experience measurement is meaningful.

As [Addy Osmani](https://addyosmani.com/) said:

> core web vitals are a set of metrics related to speed, responsiveness, and visual stability

CLS (Cumulative layout shift) is a core web vital. It measures layout stability. Images without dimensions, dynamically injected contents and web fonts are common causes of instability.

You may already know this metric, as Lighthouse reports include it.

Lighthouse is handy because it tells you which elements are responsible for the CLS Contribution. However, make sure you test it without browser extensions; they might significantly falsify the tests. Not specifically CLS but the whole performance part.

## So what to do?

There are various tools, frameworks, and techniques to improve your CSS. Here are a few acceptable practices:

* replace floats with flex or grid
* don't animate expensive properties, especially positions and dimensions
* use profiling tools and DevTools timeline
* if you don't need expensive animations and weighty web fonts, consider removing them
* always add width and height attributes to image tags
* if you preload web fonts, pay attention to the `font-display` property
* if you cannot skip this right-to-left animation on your website, use CSS transforms

## Going further

Here are useful links:

* [Understanding CRP](https://developer.mozilla.org/en-US/docs/Web/Performance/Critical_rendering_path)
* [Core web vitals explained with simple words](https://www.youtube.com/watch?v=AQqFZ5t8uNc)
* [What if we got aspect-ratio sized images by doing almost nothing?](https://css-tricks.com/what-if-we-got-aspect-ratio-sized-images-by-doing-almost-nothing/)

## Wrap up

CSS deeply affects web performances. Always try to avoid expensive CSS properties as every single rule has its cost.

There are always things to do to improve CSS, such as purge unused CSS, minifying, or bundling stylesheets, which is relatively easy to do with libraries and automatic tools.

However, understanding CSS rendering and eliminating jank are even more powerful means to improve both performances and user experience.