DEV Community

Cover image for Improve HTML and CSS performance
Yaser Adel Mehraban
Yaser Adel Mehraban

Posted on • Originally published at yashints.dev

Improve HTML and CSS performance

Recently I had a chance to present a talk at NDC Sydney about web performance and it received a great feedback.

That inspired me to write up a series of posts on each topic I covered in that talk, and who knows, maybe each of these posts would be a talk some day by their own šŸ˜ƒ.

Link to all other parts:

Part 2 use Preload/Prefetch to boost load time

Part 3 JavaScript tips and tricks

Part 4 Image optimisation

Part 5 Web font optimisation

So here we go, part one is about tips and tricks on HTML and CSS to improve the performance.

But before we jump into this, you will need to know how browsers render your page. This involves HTML, CSS and JavaScript and steps every browser takes to show your web page to end user.

The Critical Rendering Path

The Critical Rendering Path consists of five steps which are best to be seen in visual:

Critical Rendering Path

Alright now that you saw it in a picture, let me explain each step in more details.

Building DOM and CSSOM

As most of the pages consist of HTML, CSS and JavaScript. Web browsers need to know what and how to show to users and they do this by parsing the HTML page sent over network and constructing a Document Object Model (DOM). They look at HTML tags (<p></p>, <div></div>, <h1></h1>) and convert them to tokens. These tokens are then converted to nodes in parallel.

By processing the start and end tags for each token in order, the browser then establishes their hierarchy (parent and child).

This is way simpler than it looks, in the picture above imagine DOM to be a bit tree with all the nodes (branches) and their children (leaves). This tree contains all the dependencies of nodes to construct our HTML:

Document Object Model

Image from W3C website

The DOM represents your whole markup and is built incrementally by the browser. As of HTML5 the browsers support streaming HTML instead of waiting for the whole page to get sent to browser in one go. This is great because it helps the rendering to be done at the same time as the bytes are arrived.

After constructing the DOM, browser looks at any style which is referenced in the page to build the CSS Object Model (CSSOM). CSSOM describes the style rules that need to be applied to the document. This is very similar to how DOM was built, however, in this process each child inherits the styles applied to its parent - hence the name cascading style sheets.

Partial processing of styles is not possible so browsers need to wait for all the style rules to be sent over before they can start inferring what rule is applied to which nodes. This is the reason why CSS is a render blocking element.

Mix of DOM and CSSOM is something called the Render Tree. This tree includes all the nodes and their dependencies plus all the CSS rules which are applied to those.

Render Tree

After constructing all the nodes, browser needs to know which ones to show on the page. Render Tree is exactly the representation visible content on the page.

The browser stars from the root and then copies all the visible nodes from DOM and CSSOM. The steps taken are roughly as below:

  • Starting at the root, traverse each visible node
    • Some nodes are not visible like meta tags, links, etc.
    • Some nodes are hidden using CSS like display: none
  • For each node find the matching CSS rule and apply it
  • Emit visible nodes with content and they styles

Render Tree

Image from Google Developers

Layout

Now that we have all the nodes with their styles, it's time to figure out where to put them on screen. This is exactly what layout step is. The first thing which is needed is the browser window size. This is the basis for all the following calculations, since the layout depends on it to know the position and dimension of each element.

The output of this step is the Box Model which captures the exact position and size of it, plus their margin, padding, border and etc.

This step will be repeated by each change to size or when we switch between landscape and portrait on a mobile device.

Paint

This step is the last one where pixels are painted on screen which can take some time because the browser has quite a lot of work to do. This time depends on window size, how much style is applied to each node, the hardware used on device and so on.

When this step is finished, the page is finally visible in the viewport.

So what

Ok, enough with Critical Rendering Path, let's see how we can improve the web performance with tweaks on HTML and CSS.

Stream HTML to client

When sending HTML to client try to flush the buffer often instead of once at the end. This means chunks of HTML would arrive and browser can parse them as they arrive not at the end. This will help to boost the performance.

As an example, when HEAD tag is arrived browser can send other requests for assets while the rest of the HTML is arriving.

Size matters

Minifying and compressing is really important since it can reduce the payload size and reduce the HTTP response time which in turn results in better load time.

These techniques along with the right caching strategy can massively help the web performance to be improved.

Send the CSS early and keep it minimal

As you saw CSS is a render blocking element, so it should be sent down to client as early as possible. Also think of how much CSS is needed on first page load, extract the unused CSS from the main file and load them separately and later when needed.

You can also use pre-loading/pre-caching to improve the performance. These are part of PRPL pattern which was introduced by Google in 2016.

Another technique which is not used as often by developers is to use link tags inside body along with content. This is really useful as you can send a minimum amount of CSS to client even inside your HTML in a style tag and then load the rest later when needed to improve the render time.

Summary

In short, keep your recourses minimum and send them fast and optimum. Try to cut down unused CSS rules and use minification and compression to speed up the transfer.

Hope you've enjoyed reading this and are looking forward for the rest of the series šŸ˜‰.

Resources

Top comments (16)

Collapse
 
thedevcristian profile image
Paul CastaƱeda

Wow, this a great article for me to understand more of the 3 heads up of Web Development program. It'll help other people to appreciate those technologies mostly for the beginners to start their career as a developer šŸ‘Œ Cool enough.

Collapse
 
leob profile image
leob

Great explanation of what a browser is doing under the hood, no wonder browsers are among the most complex pieces of software ... also obvious now why techniques like Turbolinks are so effective, because it means the CSS and a large part of the HTML needs to be parsed just once instead of for every page.

Your explanation made me wonder though - I see that the browser has to do a lot of work (parsing etc) just to arrive at the Render Tree - what if that work could somehow be done server side (by "precompiling" an HTML page and its CSS) and the server just sends a complete "compiled" render tree to the browser - is that a crazy idea?

Collapse
 
yashints profile image
Yaser Adel Mehraban

Not at all, a small part of that is done by server side rendering, but browsers still will need to perform majority of the work. Maybe some day

Collapse
 
leob profile image
leob

Evidently yes, the browser does most of that work nowadays - I just thought, theoretically, whether some of that work could be shifted to the "build phase" - sort of a precompilation ...

Especially since all of these resources (html, css) are essentially plain text - then internally the browser builds an optimized 'binary' version - so I thought if that "optimized" version could somehow be pre-generated and downloaded ...

A bit similar to what they're doing with Javascript and Web Assembly ... OTOH if building that 'render tree' depends on a lot of dynamic variables which are not known in advance then this would of course not be practically feasible :-)

Collapse
 
jperasmus profile image
JP Erasmus

Great and informative article, Yaser. One small nitpick: there is not something like the CSSDOM, but rather CSSOM.

Collapse
 
yashints profile image
Yaser Adel Mehraban

Ooops, you're completely right. Will fix it ASAP

Collapse
 
yashints profile image
Yaser Adel Mehraban

Fixed, I had the correct full term but wrong acronym šŸ¤¦ā€ā™‚ļø

Thread Thread
 
jperasmus profile image
JP Erasmus

Yeah, nothing serious :) thanks for the post!

Collapse
 
tcelestino profile image
Tiago Celestino

great article.

Collapse
 
hepisec profile image
hepisec

Can you recommend any tool to "extract the unused CSS from the main file and load them separately and later when needed"? Would like a separate post about such tools or best practices.

Collapse
 
yashints profile image
Yaser Adel Mehraban
Collapse
 
kagundajm profile image
Kagunda JM

Great article.

Part 4 and 5 have broken links

Collapse
 
yashints profile image
Yaser Adel Mehraban

Done

Collapse
 
yashints profile image
Yaser Adel Mehraban

Thanks for letting me know, will fix it soon

Collapse
 
eavichay profile image
Avichay Eyal

Nicely done. Would recommend to read this for every web developer.

Collapse
 
yashints profile image
Yaser Adel Mehraban

Thanks