Lazy Loading Css to drastically Improve Page Speed

Feb 03, 2016 - sharathdt

Loading big non-critical CSS file at the end of the document makes sense because some times CSS takes up a lot of time to load. Learn how to defer CSS loading which makes your website super-fast. PageSpeed is a tool by Google where you can find the website speed.

Google recommends that you load critical CSS inline (e.g., page layout style) and non-critical as stylesheet. It also recommends not to use style inline attribute (e.g., <p style=...>).

When it comes to non-critical CSS like fontawesome, animation css libraries, chart css, or anything that isn’t involved in the loading of webpage can use this method to asynchronously load CSS.

Why lazy load css?

Along with loading JavaScript at the end of the document, you should also load big css files at the end. This makes your website super-fast. Because the main content loads first. So even on a slow connection, the content will be available for the user. And also, faster the website SEO friendly it is.

Many a times - on a slow connection - a user may wait for a maximum of 5 to 6 seconds and if the website is blank and still busy loading your head tag with a huge CSS file, the user may hit the back button!

You just lost a potential subscriber or even customer if you are selling something. Using a pre-loader like this one can engage the users for a few more seconds but not forever. You should not make your users wait for the main content.

In this method of lazy loading CSS, the content loads without any style and then the stylesheet loads followed by JavaScript. You may have observed this while browsing my website. This is important for a user with a slow connection. Content(visible stuff) should load at the very beginning. Style(CSS) and scripts(JS) can wait.

This ensures that even if the style or script fails to load, the user can still read the content (if the content is text). You can also minify your blog for faster loading.

I usually put a script at the end of the html document to insert the CSS link tag only after loading the document. This was helpful because my main.css is a huge file and so is the fontawesome stylesheet that loads from a CDN.

After testing in PageSpeed I found that my website is faster than ever! Do use this tool to find out what is slowing down your website.

Another very good tool to analyze website loading time is GT Metrix. This tool will give you a deep analysis on why your website is slow and provides optimized files to use.

How to load CSS at the end?

This is possible if I declare my link tag at the end of the document. But it is advised by w3c to place link tags only in the head section. So I’m using a script to place the link tag(linking CSS) in the head section.

I suggest you to check the PageSpeed Insights before and after implementing this. You sure will notice the difference.

<!-- if browser doesn't support JavaScript then use normal link tags to load CSS -->
<noscript>
      <link rel="stylesheet" type="text/css" href="/css/main.css"/>
      <link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"/>
</noscript>

<!-- load main.css -->
<script>
(function() {
    var cssMain = document.createElement('link');
    cssMain.href = '/css/main.css';
    cssMain.rel = 'stylesheet';
    cssMain.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(cssMain);
})();
</script>

<!-- load fontawesome.css -->
<script>
(function() {
    var cssFa = document.createElement('link');
    cssFa.href = 'https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css';
    cssFa.rel = 'stylesheet';
    cssFa.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(cssFa);
})();
</script>

The above code loads two CSS files. One is local main.css and the other is remote font-awesome.min.css. You can make use of this code and change it accordingly. Make sure you edit the path properly.

The last two script tags can be combined into one like this.

<!-- if browser doesn't support JavaScript then use normal link tags to load CSS -->
<noscript>
      <link rel="stylesheet" type="text/css" href="/css/main.css"/>
      <link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"/>
</noscript>

<!-- lazy load CSS -->
<script>
(function() {
    // load main.css
    var cssMain = document.createElement('link');
    cssMain.href = '/css/main.css';
    cssMain.rel = 'stylesheet';
    cssMain.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(cssMain);
    // load fontawesome
    var cssFa = document.createElement('link');
    cssFa.href = 'https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css';
    cssFa.rel = 'stylesheet';
    cssFa.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(cssFa);
})();
</script>

Keep contents within <noscript> tag in the head file. This will be loaded only of the website is loaded in a browser which doesn’t run any script or with a noscript plugin.

Problems I faced while lazy loading CSS

This problem occurred because I run Adsense on some of my websites. The AdSense code is responsive. It adjusts to the screen size mentioned in the media query. And the media query is inside main.css which I have made to load at the very end.

Adsense script loads before main.css and assumes that the screen is of full width; whereas my content is not full width. My content only goes in the center leaving some gap on both left and right sides. But AdSense has already assumed that it is full screen and adjusts its ad size to full screen and hence the ad flows out of the content.

Inline critical CSS

I struggled hard to tackle this. And after a while, I realized that I can define the width of my content with inline-css even before the AdSense code loads! Thus avoiding it to overflow. You can inline any style that you think is required in the beginning.

  <style>
    #container {
        max-width:730px;
        padding: 0 1.5rem;
        margin: 0 auto;
      }
  </style>
  <div id="container">
        <main>
         {{ content }}
        </main>
  </div>

So that solved the problem :) You can in-line important CSS this way. When the CSS file is made to load at the end, your content will not have any styling which means the content may show up on the left side of the screen for a fraction of a second, fonts appear with a default web-font and some SVGs and images may show up in their full size.

To avoid this, in-line some of the CSS which makes everything look smooth. Do not in-line too much CSS though. It is not a good practice and also your users shouldn’t get an impression that you do not know how to use CSS.

Inline SCSS in Jekyll

Jekyll supports sass preprocessor. So any number of scss files can be used to make a single main.scss file which in turn generates a main.css file upon build.

And also, Jekyll supports linking scss file directly inside html and can be changed to css file using scssify filter.

  <style>
          {% capture include_to_scssify %}
          {% include critical.scss %}
          {% endcapture %}
          {{ include_to_scssify | scssify }}
  </style>

But remember, the scss file you want to include should be inside _includes folder.

I hope this article has helped you to speed up your website. Let me know how it went. Leave a comment if you have any suggestion. I would be happy to implement it.

Thanks for reading!

Comment