Browsers cannot start rendering till all Stylesheets loaded. Visitors see blank page (or previous page) during loading of CSS so it’s especially important to load these components faster.
If you have many Stylesheet components, then visitors will have to wait more because of HTTP requests overhead.
Let’s look what can be done to reduce time to render.
1. First, we want to move CSS components to the HEAD section of HTML document so the Stylesheet will be loaded with first priority.
Worse case is when CSS included on the bottom – in this case browser waits till whole document including all components loaded before start rendering. The same thing may happen when CSS included with @import directive, so avoid using @import.
2. If we have several Stylesheets we join them into one bigger CSS file. As described in the previous post about Image Sprites, we want to reduce amount of downloaded components because of HTTP request overhead. And if in case of images there is just a delay before loading next image, in case of Stylesheet it’s a worse case: visitors see blank page until all Stylesheets loaded. One single file loads faster because there will be minimal overhead and usually it compresses better too.
3. We can go even further: if user comes with empty cache we can avoid additional request by including Stylesheet required for the page into HTML. So there will be no requests for CSS at all during loading of the page.
We can preload Stylesheet after the page loaded so for primed cache page views user already has the Stylesheet cached. This way we reduce download size and avoid HTTP requests.
More detailed:
Set a cookie when visitor comes for first time. Check the cookie on every request to determine whether the visitor comes first time or not. This way we can guess cache state of the visitor. Don’t inline Stylesheet component if visitor comes with primed cache, use an external definition instead.
Postload the external Stylesheet component when visitor comes first time (without the cookie). See example below.
Cookie named “jsl” will be set when user sees this page for first time and next requests will use external Stylesheet component.
You can set such cookie in PHP:
$is_first = !isset($_COOKIE['jsl']);
if ($is_first)
setcookie('jsl',1,time()+3600*24,'/','.site.com',false,true);
We’ve supposed that browser cache data will be removed in 24 hours and cookie expiration time set to 24 hours.
<?php if ($is_first): ?>
<style>
<?php readfile('style.css') ?>
</style>
<script>
function preload_components()
{
var ste = document.createElement('link');
ste.rel = 'stylesheet';
ste.type = 'text/css';
ste.href = 'http://www.site.com/style.css';
document.getElementsByTagName('head')[0].appendChild(ste);
}
</script>
<?php else: ?>
<link rel="stylesheet" type="text/css" href="style.css">
<?php endif ?>
The block above will output inline Stylesheet in case user comes for first time otherwise it will output link to the static Stylesheet components. You should place this code inside document head.
It will work correctly even in case user comes with empty cache (for example if our cache got forced out because cache size limit).
Style.css – global CSS file. Probably in real application instead of readfile(‘style.css’) you will include only part of the Stylesheet that’s needed to render current page.
To find out CSS that’s really required for current page, you can use a Firefox extension: Dust-Me Selectors (note that this tool may not count CSS rules for elements you assign dynamically in Javascript).
Replace existing opening
tag<body …>
with
<body … <?php if ($is_first) echo 'onload="preload_components()"'?>>
We’ve added document onload event handler that will create link DOM element if user comes with empty cache so the components will be already in cache for further page views. The external component will be preloaded only after whole page loaded and rendered so it won’t hurt performance.