The Critical Rendering Path is the sequence of tasks the browser performs to first render a page on the screen, i.e., download, process, and convert HTML, CSS, and JavaScript code into actual pixels and paint them on the screen.
The Critical Rendering Path Optimization is the process of minimizing the time spent by the browser to perform each step of the sequence prioritizing the display of content related to the current user action.
Much of this process pertains to the portion of the page that is visible without scrolling down the browser window. That section is also known as Above the Fold. For better usability, the ATF should be rendered as soon as possible, and this can be done by reducing the number of network round trips at a minimum. The resources required to render the ATF are considered critical, and optimizing the Above the Fold means minimizing the impact of critical resources on the first page render time.
In this post, we will walk through the Critical Rendering Path optimization sequence.
- First, I will provide a general overview of the browser’s tasks to render a page’s content.
- Following, I will dissect the most relevant actions we can carry out to optimize the Critical Rendering Path.
- Finally, I will list some useful (and popular) WordPress optimization plugins.
The Critical Rendering Path Sequence
Here is the sequence of steps performed by the browser to render a page:
- First, the browser downloads and parses the HTML mark-up and builds the DOM
- Then it downloads and processes the CSS mark-up and constructs the CSS Object Model
- It combines DOM and CSSOM nodes required to render the page in the Render Tree, which is a tree structure of all visible nodes
- It calculates the dimensions and position of every object on the page
- Finally, it paints pixels on the screen
The DOM
As well explained in Google’s Critical Rendering Path Optimization guide, the browser builds the Document Object Model in a four-step sequence:
- First, the browser reads the row bytes and translates them into individual characters.
- Then it converts the strings of characters enclosed within angle brackets into tokens.
- These tokens are converted into node objects.
- Node objects are linked in a tree-like data structure containing HTML content, properties, and relationships between nodes. This structure is the Document Object Model.
What is important to note here is that the browser constructs the DOM incrementally. This allows us to speed up the rendering of the page by creating efficient DOM structures.
The CSSOM
When the parser encounters a link
tag that refers to an external CSS stylesheet, it blocks the parsing and sends out a request for this resource. Once the CSS file has been received, the browser starts building a tree data structure of CSS nodes.
- The browser reads the row bytes of the .css file and translates them into individual characters
- It converts the strings of characters enclosed within curly brackets into tokens
- These tokens are converted into node objects
- Node objects are linked in a tree-like data structure that contains the CSS properties of each node and the relationships between nodes. This structure is the CSS Object Model (CSSOM).
Unlike DOM construction, CSSOM construction is not incremental. The browser can’t use a portion of a stylesheet because styles can be refined and redeclared in the same stylesheet. For this reason, the browser blocks the rendering process until it receives and parses all the CSS. This means that CSS is render-blocking.
The Render Tree
The browser combines DOM and CSSOM into the Render Tree, the final tree structure containing all nodes and properties used to render the page to the screen.
The Render Tree only contains nodes that are required to render a page. As a consequence, invisible nodes are omitted.
The browser uses the Render Tree to calculate node dimensions and position as an input for the painting process.
Layout and Paint
In the layout stage, the browser calculates the dimensions and position of each node of the Render Tree. The browser traverses the Render Tree starting from its root and produces a box model in this stage. This information is finally used to convert each node of the Render Tree into actual pixels on the screen.
Critical Rendering Path Optimization
The time required to run the entire process can be variable. It depends on the document size, the number of requests, the applied styles, the user device, etc.
One of the most relevant Google recommendations is to prioritize visible content to render the Above the Fold as quick as possible, and provides two main rules to follow:
- Structure the HTML to load the critical, above-the-fold content first
- Reduce the amount of data used by HTML, CSS, and JS resources
As well explained in Google’s PageSpeed guide, if the amount of data required to render the ATF exceeds the initial congestion window (14.6kb), additional network round trips between the server and browser will be required. On mobile networks, with high latencies, this would significantly delay the page loading (read more on latency).
The browser builds the DOM incrementally, allowing us to reduce the time required to render the ATF by structuring the HTML to load the above-the-fold first and defer the rest of the page.
But optimization does not end with the construction of an effective DOM structure. Rather, it’s a process of improvement and measurement that involves the whole Critical Rendering Path sequence.
Let’s dive deep.
Minimize Resource Dimensions
We can reduce the amount of data the browser is going to download by minifying, compressing, and caching HTML, CSS, and JavaScript resources:
- Minification is the process of removing unnecessary characters like comments and white space from the source code. These characters are instrumental in development, but they’re useless for rendering the page.
- Compression is the capability of web servers and clients to reduce the size of transmitted files to improve speed and bandwidth utilization
- Caching: every browser comes with an implementation of an HTTP cache. What we need to do is ensuring that each server response provides the correct HTTP headers to instruct the browser on when and how long it should cache the requested resources
Optimize CSS
Now we know that the browser has to wait until it fetches and processes the CSS code before rendering the page (CSS is render-blocking). But not all CSS resources are render-blocking.
CSS can be scoped to particular conditions, and we can optimize it using media types and media queries. If you’re viewing a webpage on the screen, the browser will send a request for print media type, but it won’t block the rendering of the page for this resource.
Take the following link
tag:
<link rel="stylesheet" href="style.css" />
The referenced stylesheet of this tag applies under any condition, independently from the current media type, screen resolution, device orientation, etc. This means that the CSS resource is always render-blocking.
Luckily, we can send a request for a CSS resource under specific conditions. We could move print styles into a separate file and use the media
attribute to tell the browser that the specified style sheet should only be loaded when printing the page, and it doesn’t need to block the rendering on the screen:
<link rel="stylesheet" href="print.css" media="print" />
The browser still downloads the print.css stylesheet, but it won’t block the rendering. Moreover, the browser has to download less data for the main CSS file, which would help us speed up the download. We can specify any media query on the link
attribute, so we can split the CSS into multiple files and load them conditionally:
<link rel="stylesheet" href="style.css" media="screen" />
<link rel="stylesheet" href="portrait.css" media="orientation:portrait" />
<link rel="stylesheet" href="widescreen.css" media="(min-width: 42rem)" />
Be sure your styles are actually required to render the page. You can add an appropriate value to the media tag attribute and unblock rendering if they’re not.
Media types and queries can help us speed up the page rendering, but we can do a lot more.
- Minify CSS: white space and comments only help us read CSS declarations. By removing comments and whitespace from the stylesheet, we can significantly reduce the number of bytes of a CSS file.
- Combine multiple CSS files: this would reduce the number of HTTP requests. This action is significant in mobile connections, where performance is affected by high latency (read more on latency).
- Inline critical CSS: some styles are critical because they are required to render the above-the-fold of the page. It would be best to always consider inline critical styles directly into the HTML markup to avoid additional HTTP requests. But avoid inlining large CSS files because this may require additional round trips to render the above-the-fold, resulting in a PageSpeed warning.
Speed-up Layout and Paint Processes
The time spent by the browser to layout the document depends on the number of DOM elements to layout and the complexity of those layouts.
- If you have many DOM elements, the browser could take a long time to calculate the position and dimensions of them all: avoid layout whenever possible.
- Prefer the new Flexbox model, as it’s faster than the old Flexbox and floating layouts.
- Avoid forced synchronous layout with JavaScript.
Computing element size and position takes time and reduces performance. Making the DOM as simple as possible and avoiding using JavaScript to anticipate the layout process would help the browser speed up the page rendering (read more on layout optimization).
Strictly connected to the Layout is the Paint process, which is probably the most time-consuming stage in the Critical Rendering Path sequence. Anytime you change the layout of an element or any non-geometric property, the browser triggers a paint event. Making things as simple as possible at this stage could help the browser speed up the painting process. For instance, a box-shadow
property, which requires calculations, would take longer to paint than a solid border color.
Optimizing the page painting process may not be that easy, and you should make use of your browser’s developer tools to measure how long the browser takes to trigger each paint event. You can read more on this topic in Google’s Rendering Performance guide.
Make JavaScript unblocking
When the browser encounters a script tag, it has to stop parsing the HTML code. Inline scripts are executed at the exact point in the document and block the DOM construction until the JS engine finishes running. In other words, inline JavaScript can significantly delay the initial render of the page. But JavaScript also allows to manipulate CSS properties, so the browser has to pause the script execution until it has finished downloading and building the CSSOM. This means that JavaScript is parser blocking.
In the case of external JS files, the parser must also wait until the resource has been fetched from cache or remote server, and this could heavily slow down the time to first page render.
That being said, what can we do to minimize the time spent by the browser to load and execute JavaScript?
- Load JavaScript asynchronously: the boolean
async
attribute of thescript
tag instructs the browser to execute the script asynchronously, if possible, without blocking the DOM construction. The browser sends the HTTP request for the script and continues parsing the DOM. Also, the script does not block the CSSOM construction, meaning that it won’t block the Critical Rendering Path (see MDN docs for further information about script tag attributes) - Defer JavaScript: the boolean
defer
attribute of thescript
tag tells the browser to execute the script after parsing the document, but before firing theDOMContentLoaded
event. This attribute must not be used if the src attribute is absent, i.e. inline scripts (read more on Mozilla Hacks) - Postpone inline JavaScript: many scripts do not manipulate the DOM or the CSSOM, so there is no good reason to block the parsing. Unfortunately, we can’t use
async
anddefer
attributes for inline scripts, so the only way to load them after the document has been loaded is to move them to the bottom. The advantage is that inline scripts do not require additional HTTP requests. However, inlining scripts used in several pages would result in redundant code.
Wrapping Up Optimization Rules
That’s a lot of stuff, isn’t it? Let’s take a breath, and write down a list of the optimization actions described so far.
- Minify, compress, and cache HTML, CSS, and JavaScript resources.
- Minimize use of render-blocking resources (specifically CSS)
- Use media queries on
link
tags - Split stylesheets and inline critical CSS
- Combine multiple CSS files
- Use media queries on
- Minimize use of parser blocking resources (JavaScript)
- Use
defer
attribute on the script tags - Use
async
attribute on the script tags - Inline JavaScript and move
script
tags to the bottom of the document
- Use
Now that we know the basic concepts of Critical Rendering Path Optimization, we can look at some WordPress popular optimization plugins.
Optimizing the Critical Rendering Path in WordPress
WordPress users can take advantage of several plugins that cover almost every aspect of the optimization process. You can install a fully-featured plugin or install several plugins at once, each providing specific optimization features.
If your site is hosted by Kinsta you won’t need a caching plugin because No WordPress Caching Plugins Needed at Kinsta.
W3 Total Cache
This single plugin covers almost every stage of the Critical Rendering Path optimization process. At first glance, the plugin configuration can be overwhelming. Still, once you become more familiar with the Critical Rendering Path sequence, you will be able to take advantage of a powerful performance toolset.
Here is a list of some plugin features:
- HTML (posts and pages), CSS and JavaScript caching in memory, on disk, or CDN
- Caching of feeds, search results, database objects, WordPress objects, and fragments
- HTML (posts and pages) minification
- JavaScript and CSS minification
- JavaScript optimization with
async
anddefer
- Browser caching using cache-control, future expire headers, and entity tags
- HTTP (gzip) compression
- Google PageSpeed results on WordPress dashboard
These are just a few of the many W3TC features. In this detailed guide, you can read more about all the plugin’s features, settings, and options.
WP Super Cache
WP Super Cache is another popular plugin for site performance.
It comes with many optimization features, but it’s less comprehensive than the previous W3 Total Cache and may look more affordable to novice and intermediate users.
Basically, it provides caching features and HTTP compression, but lacks resource minification and JavaScript optimization with async
and defer
attributes. However, more than one million active installs prove that the plugin is worth a try.
Autoptimize
With over 1,000,000 active installs, Autoptimize is one of the most popular free plugins for minification.
It comes with an options page divided into several sections where the site admin can separately configure HTML, CSS, and JavaScript minification.
You can also aggregate independent scripts or stylesheets and set exceptions for specific resources. Furthermore, Autoptimize allows to cache minified resources on disk or CDN and save optimized assets as static files. For finding the best settings for your WordPress site, you can follow our detailed Autoptimize guide here.
Other optimization plugins you may want to try:
Swift Performance
Swift Performance is another plugin you might want to check out. This premium plugin can help increase your performance scores and was developed specifically to help you try and achieve those 100/100 Google PageSpeed Insights scores.
Some of its main features include:
- Not only can you minify and combine CSS and javascript files, but it can create critical CSS on the fly for your pages.
- Intelligent caching, as well as AJAX and dynamic requests.
- Built-in lossless image compression.
- CDN support.
You’ll find a deeper view of WordPress optimization plugins in How to Eliminate Render-Blocking JavaScript and CSS.
Conclusions
The Critical Rendering Path Optimization is a process of improvement and measurement that requires a clear understanding of every task the browser performs to convert code into pixels and render a page on the screen. You can learn more about Critical Rendering Path in Google’s optimization guide.
Here on Kinsta Blog, we try to cover any aspect of performance optimization. Here is a list of further readings:
- Network Latency – Comparing the Impact on Your WordPress Site
- WordPress CDN – Why You Should Be Using One
- How to Optimize Images for Web and Performance
- How to Reduce TTFB to Improve WordPress Page Load Times
- A Deep Dive Into the GTmetrix Speed Test Tool
- 14 Free Website Speed Test Tools for WordPress Users
- 8 Lesser-Known (But Useful) WordPress Performance Plugins
- How to Score 100/100 in Google PageSpeed Insights with WordPress
How long does it take you to optimize the Critical Rendering Path of your websites? And which aspects of the optimization process are the toughest for you to master? Let us know in the comments below.
Great write up of HTML, CSS and JS speeds and impacts of rendering. It will very informative and I appreciate the details used.
One suggestion under the header “Speed-up Layout and Paint Processes,” you mention “Taking the DOM as simple as possible,” and “Taking things as simple as possible,” I think you meant to say “Making the DOM… and Making things as simple…
Other than that fantastic article. I thank you for your contribution.
You are correct, and we have updated the post above. Thanks for the heads up!
Very helpful article… much appreciated!
very good article! informative and complete!
Above the Fold Optimization was ‘closed’ in the WordPress plugin area on 1st April 2018 – no explanation.
Hey David,
We’ve queued this post for a content update. Thanks for the heads up!
Is there any alternative for that plugin?
Thank, Carlo, for such a well-written article.
I have a page with some heavy elements (a Slider Revolution and a calc-intensive javascript menu) which have three versions that are hidden depending on screen orientation media queries (landscape, portrait, and portrait mobile). So I would like to try your idea of segregating the CSS that way into separate files (though could be a bit tricky to do.)
I note that a few paragraphs later you recommend combining multiple CSS files to reduce the number of HTTP requests, so this is a trade-off I guess. The segregating helps more to reduce the processor load in building the CSSOM and the DOM, and the combining is better to reduce the network load, I suppose. I need to test which is more important.
What might make a bigger difference would be to somehow prevent the download of the unneeded slider variants and their assets that are otherwise only hidden by the media queries.