What’s with putting the CSS in the head?

A look into the practice of placing CSS within the head of a HTML page vs external CSS file and how it affects page performance.


Throughout my development years, the default practice has been to place all CSS in an external minified CSS. Then place this CSS file on a CDN, which would help improve loading time by hosting this file on multiple servers, one of which maybe geographically closer to the user and thus load quicker (reducing latency).

That said, there’s a growing discussion and practice around placing the CSS within the head of an HTML page. You are probably thinking, what? To understand the logic behind this we need to understand how a browser works. Although there are differences from browser to browser, the fundamentals are the same.

The Rendering Engine of a Browser
credit: https://speakerdeck.com/patrickhamann/css-and-the-critical-path

When a HTML page is loaded on a browser — the browser makes the network call which then returns a response. This response is known as the critical path. Stoyan Stefanov in 2012, describes the critical path as follows:

Critical is the path from the user following a link to the first impression and then the working experience .

So the critical path essentially relies on three factors: The HTML, CSS and the Javascript.

The path is initially split into two main paths, the HTML and CSS path. The HTML is read by HTML parsers and builds DOM and this then becomes part of the render tree. The CSS path: The CSS is read by conventional parsers, which create the CSSOM and then becomes part of the render tree.

When a javascript tag is read — the browser can behave in a number of ways. If it’s an external file — it will stop everything and download the file and then continue with the building of the DOM. It will never run the javascript because if the javascript references the CSS, which hasn’t been downloaded — it will fail. Some browsers like Mozilla tend to block all javascript activity until the CSS has been downloaded and the CSSOM have been created. Webkit — behaves slightly differently by “pre-reading”, and then holding the javascript whenever it makes a reference to the CSSOM. There are techniques such as adding defer into the script tag for HTML4 browsers or async for HTML5 browsers that prevent the javascript from appearing in the critical path. Thus reducing the dependencies in the critical path to two: the HTML and CSS.

The purpose of putting the CSS in the head is to reduce or rather try and keep much of the CSS as possible off the critical path by downloading it as quick as possible. To understand this, we need to look at the anatomy of a network request. See below:

credit: https://speakerdeck.com/patrickhamann/css-and-the-critical-path

When a network request is made, there is latency involved (the dark green, orange and light green blocks). This is something we cannot really eliminate unless the technology for transferring information makes a significant leap. So the point of putting the CSS in the head is to eliminate the latency in the network request, ie there is no network request for the CSS — so it the CSSOM building starts immediately. By doing this, the point in which the render tree is created happens sooner rather than later in the process. Thus the page performance greatly improves.

Below is the current the network diagram of the login page for for a web app.

(caveat: I’ve literally copied the CSS, which was unminified, the html tags and scripts that it uses and placed them on a different server)

As you can see it takes 378ms to load. In comparison, the next diagram below, I’ve minified the CSS and placed it into the head of the html page.

CSS is placed within head of the HTML Page

In this case the page loads in 225ms. That’s near 150ms faster than the unmodified version. One might argue that the significance of 150ms is irrelevant, but before you do, read this article.

I’ve had a look at Google and below are the findings of their current site.

As you can see, putting the CSS in the head means it isn’t part of the network request — in otherwords it’s been removed from the critical path. For Google to load 182ms to load and then the DOM content loaded is also 182ms. Effectively, it’s instantaneous.

Google (as demonstrated above), Bing and the Guardian are just some of the companies that are doing this now. Some are even differentiating their CSS into two parts, a core CSS (placing this within the head) and a non core CSS, having this as an external CSS. There are some ramifications for doing adopting this approach — I shall discuss this in another post.

Placing your CSS within the head of your HTML page does increase the performance of your web page. I feel it is only a matter of time before this approach becomes a common practice.

Thanks to Patrick Hamann for his inspiring talks he did on web page peformance last year, which I owe a lot of this post to. Also to Paul Irish and Tali Garsiel for their incredibly informative article: How Browsers Work: Behind the scenes of modern web browsers.