CSS delivery optimization: How to defer css loading?

102,642

Solution 1

If you don't mind using jQuery, here is a simple code snippet to help you out. (Otherwise comment and I'll write a pure-js example

function loadStyleSheet(src) {
    if (document.createStyleSheet){
        document.createStyleSheet(src);
    }
    else {
        $("head").append($("<link rel='stylesheet' href='"+src+" />"));
    }
};

Just call this in your $(document).ready() or window.onload function and you're good to go.

For #2, why don't you try it out? Disable Javascript in your browser and see!

By the way, it's amazing how far a simple google search can get you; for the query "post load css", this was the fourth hit... http://www.vidalquevedo.com/how-to-load-css-stylesheets-dynamically-with-jquery

Solution 2

A little modification to the function provided by Fred to make it more efficient and free of jQuery. I am using this function in production for my websites

        // to defer the loading of stylesheets
        // just add it right before the </body> tag
        // and before any javaScript file inclusion (for performance)  
        function loadStyleSheet(src){
            if (document.createStyleSheet) document.createStyleSheet(src);
            else {
                var stylesheet = document.createElement('link');
                stylesheet.href = src;
                stylesheet.rel = 'stylesheet';
                stylesheet.type = 'text/css';
                document.getElementsByTagName('head')[0].appendChild(stylesheet);
            }
        }

Solution 3

This is how you do it using the new way:

<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
  • link rel="preload" as="style" requests the stylesheet asynchronously.
  • The onload attribute in the link allows the CSS to be processed when it finishes loading.
  • "nulling" the onload handler once it is used helps some browsers avoid re-calling the handler upon switching the rel attribute.
  • The reference to the stylesheet inside of a noscript element works as a fallback for browsers that don't execute JavaScript.

Solution 4

In addition to Fred's answer:

Solution using jQuery & Noscript

<html>
  <head>
    <style>
      .blue{color:blue;}
    </style>
    <script type="text/javascript" src="../jquery-1.4.2.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function(){
        if($("body").size()>0){
                if (document.createStyleSheet){
                    document.createStyleSheet('style.css');
                }
                else {
                    $("head").append($("<link rel='stylesheet' 
                    href='style.css' 
                    type='text/css' media='screen' />"));
                }
            }
        });
    </script>
    </head>
  <body>
    <div class="blue">
      Hello, world!
    </div>
  </body>
</html>
<noscript><link rel="stylesheet" href="small.css"></noscript>

from http://www.vidalquevedo.com/how-to-load-css-stylesheets-dynamically-with-jquery

Using pure Javascript & Noscript

<html>
  <head>
    <style>
      .blue{color:blue;}
    </style>
    <script type="text/javascript">
          var stylesheet = document.createElement('link');
          stylesheet.href = 'style.css';
          stylesheet.rel = 'stylesheet';
          stylesheet.type = 'text/css';
          document.getElementsByTagName('head')[0].appendChild(stylesheet);
    </script>
    </head>
  <body>
    <div class="blue">
      Hello, world!
    </div>
  </body>
</html>
<noscript><link rel="stylesheet" href="small.css"></noscript>

Solution 5

Try this snippet

The author claims it was published by Google's PageSpeed Team

<script>
    var cb = function() {
    var l = document.createElement('link'); l.rel = 'stylesheet';
    l.href = 'yourCSSfile.css';
    var h = document.getElementsByTagName('head')[0]; h.parentNode.insertBefore(l, h); };
    var raf = requestAnimationFrame || mozRequestAnimationFrame ||
              webkitRequestAnimationFrame || msRequestAnimationFrame;
    if (raf) raf(cb);
    else window.addEventListener('load', cb);
</script>
Share:
102,642
RafaSashi
Author by

RafaSashi

About Rafasashi Web development primarily in php and javascript I am currently managing RECUWEB.COM an IT company providing webdesign, web development, digital marketing, advertising and hosting services all over the world. @rafasashi | Careers 2.0 | LinkedIn | Recuweb.com

Updated on July 24, 2022

Comments

  • RafaSashi
    RafaSashi almost 2 years

    I am trying to optimize the CSS delivery following the google documentation for developers https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery#example

    As you can see in the example of inlining a small CSS file the critical CSS in inlined in the head and the original small.css is loaded after onload of the page.

    <html>
      <head>
        <style>
          .blue{color:blue;}
        </style>
        </head>
      <body>
        <div class="blue">
          Hello, world!
        </div>
      </body>
    </html>
    <noscript><link rel="stylesheet" href="small.css"></noscript>
    

    My question regarding this example:

    How to load a large css file after onload of the page?

  • RafaSashi
    RafaSashi over 10 years
    Thanks for the jquery function I will definitely use it! For #2 the disable option has been removed from the tools in firefox up to version 23 and I had to use the about:conf entries. I confirm the css is loaded using noscript out from html.
  • Jayen
    Jayen about 10 years
    i'm confused at how the second one's javascript is different from just putting the link at the end of the head.
  • RafaSashi
    RafaSashi over 8 years
    The first solution requiers the jQuery library whereas the second one doesn't
  • Jayen
    Jayen over 8 years
    I'm not asking the difference between the first and second. The second doesn't wait for DOMContentLoaded so it seems to be the same as <link href="style.css" rel="stylesheet" type="text/css">.
  • Karim Samir
    Karim Samir over 8 years
    @Fred you have an error in your code it should be $("head").append('<link href="'+src+'" rel="stylesheet" type="text/css">');
  • Fred
    Fred over 8 years
    @KarimSamir Back in the day, you needed to wrap it in $ to instantiate it as a DOM element. Not sure if this is still the case.
  • Huy Nguyen
    Huy Nguyen about 8 years
    I applied this technical and my homepage passed Optimize CSS delivery rule, however, this not work in details page, I use the same script because this script in layout file.
  • Taylor D. Edmiston
    Taylor D. Edmiston almost 8 years
    @Jayen Your statement is correct. It looks like current solutions accept the trade off of not deferring loading when JavaScript is disabled (under the assumption that it is hopefully uncommon).
  • Jonas T
    Jonas T over 7 years
    Same here. It only optimize home page's CSS delivery rule. Doesn't work on all other page. any idea?
  • Jonas T
    Jonas T over 7 years
    It only solved home page's CSS delivery rule to 100/100. Doesn't work on all other page. any idea? Other pages are still showing "Eliminate render-blocking JavaScript and CSS in above-the-fold content" issue.
  • Raja Khoury
    Raja Khoury over 7 years
    Did you check if other pages have additional stylesheets loaded ? Although i posted this answer I have never used this method. I load my CSS the old fashion way and try not to obsess with Google page speed score. Minify & optimize your css and work towards a better content to rank up.
  • rolu
    rolu over 7 years
  • Sparky
    Sparky over 7 years
    Isn't having anything after a </html> tag invalid HTML?
  • Shawn Rebelo
    Shawn Rebelo about 7 years
    Using either of that code actually reduces my score, not improve. Before using their "suggested defer code" Score: 77. After using (either one). Score: 69. So uh... no thanks.
  • authorandrew
    authorandrew about 7 years
    This solution works perfectly, but the loaded CSS file is never cached, meaning there's always an 'unstyled' flash before it loads. I am using critical CSS for very basic CSS, but it's still a very drastic change between the two. Any way to cache the file as it's dynamically loaded?
  • Don Dilanga
    Don Dilanga over 5 years
    this script may defer CSS, but it render blocks the page with jquery file.so it's not recommended as a good solution.
  • nulll
    nulll over 4 years
    @authorandrew Chrome 80 works fine, on Firefox 74 there is the cache problem you mentioned
  • JAT86
    JAT86 almost 3 years
    Maybe using Base64 images (for small images like icons and logos) will help.
  • db2
    db2 over 2 years
    It's 2021, using jQuery should not be the accepted answer.