Understanding the Critical Rendering Path

Posted on in Consulting

Critical Rendering PathOne of our clients complained recently that their website was too fast. Yeah, they wanted to slow it down so their audience could kick back, relax, and wait a little longer for the page to load. Just kidding.

We are going to address two web development trends in this article: web pages are getting fatter, and the average device speed is getting slower. Yes, desktops are now in the minority position among devices. Smartphones and tablets are where the user majority lurks. And don’t be fooled by 4G advertising hype that is all about bandwidth, the network overhead and latency is much higher on 4G than it is for Wi-Fi or wired networks. Also, to get max speeds you need consistent max quality of connection, too. Is your 4G icon always at four bars?

To deal with both of these trends, engineers have been putting extra effort into understanding exactly what happens inside a browser during the rendering process, and how to fine-tune that process. In the days of old, when we wanted to speed up a website, we would put it on a faster server (maybe), or reduce the size of the page (what engineers call “page weight”), so that it would download faster. All of this works, of course, but only to a point and even then, only if you have those luxuries.

But page download speed is a bit of a red herring, what we really want is page rendering speed. If the “above the fold” content renders in one or two seconds, and the rest of the content takes another five or six seconds, how big a deal is that?

Increasing page rendering speed is easier said than done, though. To get there we need to understand what has been defined as the “Critical Rendering Path”, such that we can shorten it.

Critical Rendering Path

The Critical Rendering Path is defined by engineers as the code and resources required to render the initial view of the page. We call it “critical” because we get a blank, “white screen of death until all the critical elements render. The “initial view” can be translated as “above the fold” content.  The path potentially consists of a fairly complex set of interactions. If we know how the pieces impact each other, we can then make decisions about how to arrange them in an optimal manner.

The components of the the Critical Rendering Path are:

  • Network Overhead (Web Server Response Time): Remember, cell networks ALWAYS have a much slower round trip time; they have a higher “latency”. Always!
  • HTML code: We just can’t have a web page without the HTML being fully downloaded and the Document Object Model (DOM) tree built by the browser. Rendering can only start after that happens.
  • CSS: CSS has its own object model, the CSSOM, which also must be constructed and applied to the DOM. CSSOM construction blocks the rendering process.
  • Webfont: These are fonts that have to be downloaded.
  • JavaScript: JavaScript can interact with both HTML and CSS, and is potentially the most disruptive. Unless extra steps are taken, browsers stop rendering while JavaScript is being downloaded and executed.

Notice that images, the heaviest part of most web pages, are not on the above list. That is because they have no impact; they are just plain content which require no special handling. The actual rendering process (the DOM tree construction) is not dependent on images and is not blocked by image loading. Image downloading takes place in parallel while the DOM is being built and readied, and perhaps afterwards. Of course, images are important, and we need them. But they are simply inserted into the DOM and displayed as they are downloaded, once the DOM is in a ready state. Image loading should of course be optimized, but they are not “critical”.

Let’s take a closer look at these components. As to network overhead, of course we need a fast server response. Usually this is measured as “time to first byte”. We can use tools like webpagetest.org to measure server response and other metrics. An optimal “first byte time” should be less than 200 milliseconds.

ttfb

Web content is downloaded by the browser in “chunks”. This appears to happen in a single, steady stream since it happens quickly, with each chunk downloading in close succession. Each“chunk” consists of a packet of data of up to 14KB. Because of this, the fastest loading web page possible is a page consisting of 14KB or less. A 15KB page will require two chunks and a 29KB page will require three chunks and so on and so on.

As an example if we create a simple web page that just says “Hello World”, with no images, no CSS, and no JavaScript, we will have a page with well less than 14KB. With a reasonable Internet connection and a non-overloaded server, this page will download and fully render in  less than 1 second. That’s what we like!

Now, a “Hello World”  page is easy, there’s no extra effort required. Our mission, should we accept it, will be to take an average web page of 1.2MB and get its critical components shoehorned into that first 14KB — those elements that are critical for the above the fold content. The rest of the page content can safely be deferred, if not within the first 14KB, then as close as we can get to that goal.

Again, tools like webpagetest.org are invaluable for finding  bottlenecks and to see what happens with each resource. Waterfall charts are also very illustrative about what is going on with your page.

waterfall-highlights-sm

Next, we need minimal resources in the document HEAD. Any styles and JavaScript should be inline and very minimal. Additional styles and JavaScript can be loaded later, preferably asynchronously. There is definitely extra effort involved in this.

Webfonts are now a common resource for modern web content. There are lots of variables here that can impact performance. Web pages won’t render until the font resources are known and fetched. So, let’s be sure we are only including the fonts we need and only the character sets we need too. English only site? Then we just need latin1 characters. This can greatly reduce font file size. Also make sure the font resources are compressed, and that the browser will cache these resources.

Tips:

  1. Minimize HEAD content. Anything in HEAD has to be processed before the DOM is created and therefore blocks rendering. In an ideal world, the full HTML and the components referenced in HEAD should be less than 14KB.
  2. All Critical Path resources should be served from the same domain in order to minimize DNS lookup time.
  3. Eliminate redirects; they take time.
  4. Rendering is faster and more efficient when CSS comes before JavaScript.
  5. JavaScript should be served asynchronously as much as possible. If not asynchronously, it should be deferred, but asynchronously is best.
  6. Combine and minify all CSS and JS files, of course.
  7. Load only the resources you need for that page.  This seems obvious, but some frameworks and CMS’s like to pull in all CSS and JS on every page, whether used or not. Remove unused resources!

Resources:

  1. Authoring Critical Above the Fold CSS 
  2. Optimizing the Critical Rendering Path, an in depth article by Google engineer Ilya Grigorik.
  3. Optimizing Webfonts, also by Ilya Grigorik
  4. WebPageTest.org,  great performance tuning resource