This article is part of a series created in partnership with SiteGround. Thank you for supporting the partners who make SitePoint possible.
I’ve always thought deciding how and when to load CSS files is something best left to browsers. They handle this sort of thing by design, why should developers do anything more than slap a link element with
href="style.css" inside the
<head> section of the document and forget about it?
Apparently, this may not be enough today, at least if you care about website speed and fast-rendering webpages. Given how both these factors impact on user experience and the success of your website, it’s likely you’ve been looking into ways in which you can gain some control over the default way in which browsers deal with downloading stylesheets.
In this article, I’m going to touch on what could be wrong with the way browsers load CSS files and discuss possible ways of approaching the problem, which you can try out in your own website.
The Problem: CSS Is Render Blocking
If you’ve ever used Google Page Speed Insights to test website performance, you might have come across a message like this:
Here Google Page Insights is stating the problem and offering a strategy to counteract it.
Let’s try to understand the problem a bit better first.
Browsers use the DOM (Document Object Model) and the CSSOM (CSS Object Model) to display web pages. The DOM is a model of the HTML which the browser needs in order to be able to render the web page’s structure and content. The CSSOM is a map of the CSS, which the browser uses to style the web page.
CSS being on the critical rendering path means that the browser stops rendering the web page until all the HTML and styles information are downloaded and processed. This explains why both HTML and CSS files are considered to be render blocking. External stylesheets especially involve multiple roundtrips between browser and server. This may cause a delay between the time the HTML has been downloaded and the time the page renders on the screen.
The problem consists in this delay, during which users could be staring at a blank screen for a number of milliseconds. Not the best experience when first landing on a website.
The Concept of Critical CSS
Although HTML is essential to page rendering, otherwise there would be nothing to render, can we say the same about CSS?
Of course, an unstyled web page is not user friendly, and from this point of view it makes sense for the browser to wait until the CSS is downloaded and parsed before rendering the page. On the other hand, you could argue that not all style information is critical to building a usable page. What users are immediately interested in is the above the fold portion of the page, that is, that portion which users can consume without needing to scroll.
This thought is behind the dominant approach available today to solve this problem, including the suggestion contained in the message from Google Page Insights reported above. The bit of interest there reads:
Try to defer or asynchronously load blocking resources, or inline the critical portions of those resources directly in the HTML.
But how do you defer or asynchronously load stylesheets on your website?
Not as straightforward as it might sound. You can’t just toss an
async attribute on the link element as if it were a
Below are a few ways in which developers have tackled the problem.
Take Advantage of Media Types and Media Queries to Minimize Render Blocking
Ilya Grigorik illustrates a simple way of minimizing page rendering block which involves two stages:
- Split the content of your external CSS into different files according to media type and media queries, thereby avoiding big CSS documents that take longer to download
- Reference each file with the appropriate media type and media query inside the link element. Doing so prevents some stylesheet files from being render blocking if the conditions set out by the media type or media query are not met.
As an example, references to your external CSS files in the
<head> section of your document might look something like this:
<link href=”style.css” rel=”stylesheet”>
<link href=”print.css” rel=”stylesheet” media=”print”>
<link href=”other.css” rel=”stylesheet” media=”(min-width: 40em)”>
The first link in the snippet above doesn’t use any media type or media query. The browser considers it as matching all cases therefore it always delays page rendering while fetching and processing the resource.
The second link has a
media="print" attribute, which is a way of telling the browser: “Howdy browser, make sure you apply this stylesheet only if the page is being printed”. In the context of the page simply being viewed on the screen, the browser knows that stylesheet is not needed, therefore it won’t block page rendering to download it.
Finally, the third link contains
media="(min-width: 40em)", which means that the stylesheet being referenced in the link is render-blocking only if the conditions stated by the media query match, i.e., where the viewport’s width is at least 40em. In all other cases the resource is not render blocking.
Also, take note that the browser will always download all stylesheets, but will give lower priority to non-blocking ones.
To sum up, this approach doesn’t completely eliminate the problem, but can considerably minimize the time browsers block page rendering.
Using the preload Directive on the Link Element
Continue reading %Tackling Render Blocking CSS for a Fast Rendering Website%