Why CSS slows down your page
Latly, I've been working on improving our web site's mobile web experience, from a performance perspective.
I started by inlining all the style definitions to be in the HTML head, instead of doing an extra calls to get the css file.
This worked out great! Although the page size increased, avoiding the extra calls had significant improvement, especially in a mobile device.
But... This will not scale. Using css files has many advantages, like caching, maintainability, etc...
I added a single css file to my page, and was stunned by the results.
The Page Load time and Start Render time have doubled!
I compared the results of both a page with and without a css link, and it seems the rendering of the page starts only after the css file has finished downloading.
This article explains it more in depth, but the gist of it is when a browser stumbles upon a css link, it immediately stops the rendering of the page, and waits for the css to download, while the rest of the page is still being processed of course.
You can simulate this with the following markup:
<html>
<head>CSS test</head>
<body>
<div class="before">
Before a css call is made - this will render immediately
</div>
<link rel="stylesheet" type="text/css" href="css-test.css">
<div class="after">
After a css call is made - this will render after a long time
</div>
</body>
</html>
And the following css:
.before { background: green }
.after { background:red }
The first div will render immediately. The browser will process the link
tag, and will stop rendering the page. When the css file will be downloaded, the browser will reprocess the DOM and render the page again.
As you can understand, this is the basic behavior of the browser.
How to improve
I'll start at the end - I succeeded at improving the Start Render time of my page:
I used an external css file and this only added 200ms to the page compared to using inline styles
CSS links should be first in the head tag
This will make the browser issue the requests as early as possible, which will increase your chances to download them faster.
Use the same domain as your web page
One of the oldest tricks in the book regarding resource downloading is to use a different domain for your resources. This is well known technique which is the direct result of the requests per domain limitation of browsers: A browser is limited by the numbers of calls you can do per domain (four in most browsers).
While this does wonders on desktops, in mobile it is problematic at best (especially for css resources), since creating the initial connection to each new domain takes longer on a mobile device, which I've seen in my tests that are clearly the most wasteful things, from a network perspective (DNS lookup and establishing the initial connection to the new domain):
If you move your css file to the same domain as your web site, your browser will use the same connection, since it is cached from the request, so it won't have to do a DNS lookup and open the connection again, and by that you are reducing two thirds of your network time for the resource.
The downside of course, is if you have more than one css file, you'll have a problem doing more than the limited number of requests per you domain.
More so, if for some reason you need to do ajax requests while rendering, in which case you'll have to wait.
Limit the number of css resources
I recommend no more than two css links per page.
The more resources you'll have, the longer it will take your page to render.
Its that simple.
I used a mixed approach - single css file for the page, and style
in the head of the page for the stuff above the fold.
Size does not matter
Well, it does, but not as much as you think.
If you minify your css properly you won't have any problems.
Initially I thought the base64 images I had in the css file caused the high network time, but it had little effect when I removed them.
Keep a close watch on these and only download the css you really need.
The async approach
Browsing around looking for more answers, I found out this library. Using it, causes the rendering of your page to continue and it will load the css in the background.
The problem with this approach is the rendering of the page will look strange - first you'll see and unstyled page and when the css will be ready, the page will be re-rendered.
What I recommend is to use style
definitions within the HTML head section for everything you render above the fold, and download the rest of the css async.
Summary
By following these guidelines, with an external CSS request, I've turned this:
into this:
These simple steps will make the experience of your users a lot better.
For mobile users especially, which do not like to wait a long time before seeing something when they click a link.
I'm still looking for tips on how to make a web page render faster, so if you have one, don't hesitate to share