Unfolding Critical CSS

Inlining critical CSS is an optimization technique designed to make your site render blazingly fast. But does it?

A website is one or more web pages bound together by a domain, hyperlinks, commonly used assets, and the browser cache. Web pages are not websites. Websites are not web pages. Optimizations that lighten the payload of a web page may increase the payload of a website.

What is the difference between optimizing front end web pages and websites? How are files cached by the browser? When should you be designing for first visits and when should you be leveraging the browser cache? What is the payload of a website how is it affected by inlining performance techniques? Let us explore and discuss the differences between optimizing critical CSS for web pages and websites together.

Inlining critical CSS directly in your HTML improves the load time of your web page’s first visit but as your site is browsed the optimizations intended on making first impression snappier may slow subsequent visits down.

Critical CSS makes your site render blazingly fast — especially on mobile.
CSS Stylesheets block rendering. Until a user’s browser has requested, received, downloaded and parsed your stylesheets, your page will remain blank. By reducing the amount of CSS the browser has to go through, we can get the page to render much, much faster.
Unfortunately it’s quite tedious to manually determine what css should be considered critical for a page. This tool removes that pain as it automates the process for you.
About Critical CSS

All true. Well, mostly true. Critical CSS focuses so much on optimizing web pages it looses focus of optimizing websites. If we can agree a website is a series of web pages, we can agree optimizing for a single page does not translate to optimizing for a site. Web pages are not websites, so decide before you start optimizing be sure and decide which one to target.

The first visit to a website is via a web page. In that first visit web browsers will cache external assets. Cached assets don’t have to be re–downloaded on subsequent visits. Leveraging the browser cache is a great way to optimize your website but does not optimize the load time of your first visit. In fact loading external assets slows your initial load down. Shipping inline styles that do not leverage the browser cache is a great way to optimize your first visit but by no measure optimizes the browsing experience of your website.

Ask Yourself

Are you building a single web page that users will visit once never to return to or are you building a multi–page website that most users click around on for a while? Will the content of your website be frequently updated? Do you expect users to return to the page within a short period of time? Regardless of what your users are doing now ask yourself what do you want them to do and design for that.

Inlining CSS

The cost

  • Unable to leverage the browser cache
  • Heavier HTML payload
  • Heavier site payload

The reward

  • Faster initial page load times
  • No blocking HTTP request
  • No latency in retrieving a cached file

If you are building a one page experience and your only performance concern is the first time the page loads then inlining CSS totally makes sense. Otherwise if you concerned with refreshing that page or visiting another page of the site within a short period of time, inlining CSS will send excessive bytes on each subsequent page request. If you keep to inlining only “critical CSS” such as the first 14kb or so of CSS to render the “above the fold” content this cost the amount of weight you are adding to your HTML isn’t much. Especially if GZIP is enabled, this won’t slow down your time to first byte on subsequent visits much.

Critical CSS avoids a blocking HTTP request by moving styles from external CSS styleheets to inline HTML. There is a toll all who inline styles must pay. Inlining CSS sidesteps the browser cache and cannot leverage the hyper–performance gained when assets are cached. Yes this will improve the perceived load time of the first visit but is that the only thing you are concerned about?

Design for Success

If you want a website that people click around on, design for a website that people click around on. If you want a website whose content will be frequently updated, design for a website whose content will be frequently updated. Design is about solving problems, but it isn’t just about solving the immediate problem. Challenge yourself to step back and consider the problems you will have once your project goals are met. You are a good Designer. Good Designers ultimately solve problems so plan for it!

A Blazingly Friendly Mobile Site Experience

Critical CSS makes your site render blazingly fast — especially on mobile. — About Critical CSS

It might be more accurate to say that Critical CSS makes your pages render blazingly fast the first time a user visits them. If they refresh the page or visit another page of the site, Critical CSS increases your payload by not leveraging the browser cache. If they visit a URL that uses location hash to jump passed “the fold” to a specific part of the page then all the performance tuning you did for making above the fold content appear quicker were pointless.

Considering Critical CSS often increases the full browsed payload of your site, it is bold to claim to improve mobile site performance. Inlining critical styles improves initial page performance significantly. It does not improve returned visits to that page or visits to another page that makes use of those same inline styles. Ok, so there is a difference between optimizing for web pages an websites. But how do you know which to build for and what if you need to switch back and forth?

External stylesheets are blocking. Yikes! Afterwards the first request though they are pretty snappy. With proper cache headers, cached files are stored snuggly safe and sound in the browser cache where they can be re–requested without much latency. Once that upfront cost is paid you can re–deliver that same data on subsequent requests practically for free. If you do enough legwork upfront to optimize your site you may find yourself willing and able to ante–up for the cost of a blocking request to a stylesheet.

Bandwidth as Accessibility

Users on Capped Data Plans Pay by–the–Byte. If you were to evaluate the user experience of a movie you saw would you factor in the cost of the ticket? Users that enter your experience on capped data plans appreciate you being considerate on their data usage as they browse. Otherwise you may be unjustly charging them excessively to browse your experience. All the more reason to leverage the browser cache wherever we can. We may diminish our PageSpeed slightly score by doing so but our website is more user friendly. You can’t put a number on user exerpience, so don’t.

The Quiz

If you inline 20kB of the same critical CSS on 10 different pages how many kB of styles have you sent them?

How many HTTP Requests have you sent them for your inline styles?

If you load 20kB of the same critical CSS styles from a cacheable external stylesheet on 10 different pages how many kB of styles have you sent them?

How many HTTP Requests have you sent them for your external stylesheet?

Leveraging the Browser Cache

If you inline an average of ~20kB of critical CSS on each page and a user visits 10 pages that make use of those same styles you’ve served them 180kb of avoidable weight. That’s ~20kB of the same uncacheable non–blocking styles being downloaded 10 times (once for each page) vs ~20kB of blocking styles being downloaded once as part of a common stylesheet. The number of average page views per user should be taken into consideration when architecting your CSS delivery method.

Loading assets from common CDNs is a great way to leverage the browser cache. If you get lucky, your user already visited another website that used the same version of the same frameworks and when they arrive at your website for the first time those large frameworks don’t have to be requested at all! An of this is the HTML5 Boilerplate technique of loading jQuery from a common CDN. This means that all the websites that utilize HTML5 Boilerplate benefit from first attempting to load jQuery from a common CDN which may already be cached in the user’s browser.

What are the odds a user will have your framework already cached? Better than 0, and that is all that matters because there is no chance they will show up with a prepped cache if you are not loading frameworks from comomon CDNs.

Don’t Forget the Hash

In a proven effort to speed up first visits, Critical CSS forgets one important thing: the location hash.

The location hash property allows any part of an HTML page to be directly linked to. It is unsafe to assume the top of your page will always be the first thing a user sees. Are you using the location hash to deep link to any parts of your website? May you utilize the ability to do so in the future? Are there ids on thinks like sections and headers so that users could link directly to sections of the website on their own?

The Fold?

Modules like grunt-criticalcss will determine what styles are and are not critical based off what is and isn’t above “the fold”. The concept is that if we look at what is displayed in the top 768px of our website on a 1024x768 viewport then we can consider any styles used in that section of the page critical, and everything else uncritical.

If there ever was a fold responsive design killed it.

The components visible within a desktop viewport may be completely different than the ones visible within a mobile viewport. But that’s not all. Stylesheets block for a reason.

Stylesheets Block for a Reason

By default browsers will cache most requests to stylesheets, images, and external JavaScript files. Unless configured otherwise, the HTML data itself will not be cached by the browser. This is because browsers know the HTML they consume can become outdated before it is even done being consumed. Allowing your HTML itself to be cached on the client side for a short period of time such as 5 minutes can be a clever way to make a site feel ultra–snappy as it is browsed.

Stylesheets are meant to load things the page needs right then right now. That’s why they block. If you chose to use loud frameworks like Bootstrap or Foundation your CSS weight got away from you quickly. Next thing you know you have these loud, heavy, blocking stylesheets loading on pages that use only a small percentage of the styles within them. Your root issue isn’t that external stylesheets were designed to block. Your root issue is your stylesheets were designed to block too.

Measure the percentage of your styles that are used on your pages. Consider measuring the percentage of your styles used on your whole website. If you are loading a significant percentage of styles that are never used then that’s square one. Start there. Critical CSS didn’t get you into this mess and it can’t get you out of it.

TL;DR

  • HTML often isn’t cached
  • external stylesheets are often cached

Global styles should be delivered once. Only once. With little exception, when they are are delivered they should be delivered in a cacheable manor.

Focus on delivering styles that are relevant to the specific page rather than a specific part of the page. If you are using id or name attributes in your markup people will find ways to share more specific parts of your pages. If you ever use the location hash to link to specific parts of your pages in your social media campaign you already inviting people to skip right passed “the fold” of your webpage.

What Else?

Here are some things you should consider prior to inlining styles:

Once you have made the above considerations you should have a pretty snappy site. If your minified CSS weight is near 100kB, is there anything you can do to lighten your CSS payload? What percentage of loaded style are being used on your pages?

Still not snappy enough? At this point you may consider inlining CSS to improve perceived first loads.

Don’t Listen to Me

There is no absolute right answer here. As a Web Designer it is up to you to analyze your project and the weight of your assets against the browsing patterns of your users and make an educated guess on the best approach to take. Do your own performance testing. Test for the visitor patterns you have as well as the ones you want. If the visitor patterns you have are not the visitor patterns you want at that point you can decide to fail by never allowing yourself to succeed or you can design for the results you want. Usually clients want a website that people would return to or browse a little before leaving. Think twice before “optimizing” with a tool that is incapable of cashing in by leveraging the browser cache.