skip to Main Content

Google recommends (https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery) using following JS code to optimize page speed (async CSS loading)

<script>
  var cb = function() {
    var l = document.createElement('link'); l.rel = 'stylesheet';
    l.href = 'small.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>

When I use the code above, Page Speed Insights (https://developers.google.com/speed/pagespeed/insights/) recognizes it and gives the page higher score. But the problem is, that this code does not work in older IEs.

For example, IE 8 throws an error “Object requestAnimationFrame is not defined”. The problem is obvious, IE 8 does not support RAF, so it throws an error because of undefined object.

I need the website to be functional also in these older IEs, so I decided to update my code as following:

<script>
function loadCss() {
    var l = document.createElement('link');
    l.href = 'http://static.xyz.com/css/style.min.css?v=23';
    l.rel = 'stylesheet';
    l.type = 'text/css';
    l.media = 'screen';
    document.getElementsByTagName('head')[0].appendChild(l);
}

if (typeof requestAnimationFrame === 'function') {
    requestAnimationFrame(loadCss);
}
else if (typeof mozRequestAnimationFrame === 'function') {
    mozRequestAnimationFrame(loadCss);
}
else if (typeof webkitRequestAnimationFrame === 'function') {
    webkitRequestAnimationFrame(loadCss);
}
else if (typeof msRequestAnimationFrame === 'function') {
    msRequestAnimationFrame(loadCss);
}
else if (typeof window.addEventListener === 'function') {
    window.addEventListener('load', loadCss);
}
else {
    window.onload = loadCss;
}

This code is not so pretty, but it works properly in IE7+, Firefox, Chrome etc. But when I test it via Page Speed Insights, it does not recognize that the CSS is loaded asynchronously and does not give me a higher score (it shows an error same as if the CSS was loaded synchronously via ).

My question is: is there an error in my code I am not aware of, or Google simply does not recognize this way of inserting async CSS. It is absolutely important for me, that the code works properly, but I would like to achieve higher score in Page Speed test, as it would be a benefit for SEO purposes.

I am not an expert in Javascript nor layout painting and things like these, but I could not find an explanation of what is going on or where the problem could be.

Thanks in advance for any explanations or hints what to look for.

3

Answers


  1. Your code loads css asynchronously, yes. So most likely google just don’t recognizes your way. You may try to replace window.onload with attachEvent for ie support maybe that will help

    Login or Signup to reply.
  2. I faced the same issue, in my case several mobile ‘User Experience’ issues cause Page Speed Insights analyzed the site before my asynchronously loaded CSS could kick in.

    Doing this was a pain, but ended up extracting the basic styling that addressed the UX issues, then placing a minified version of that inline in the header while leaving the bulk of the CSS to be loaded asynchronously through js.

    Wish there was a better solution.

    Login or Signup to reply.
  3. This code seemed to do the trick for me (it loads async CSS, Google PageSpeed accepts it and it works on older browsers):

    <script>
    var cb = function(){
      var styles = ["http://mycdn.co.uk/stylesheet1.css", "http://mycdn.co.uk/stylesheet2.css"];
      for( var i = styles.length - 1; i >= 0; i-- )
      {
        l = document.createElement( 'link' );
        l.rel = 'stylesheet';
        l.href = styles[i];
        h = document.getElementsByTagName( 'head' )[0];
        h.insertBefore( l, h.childNodes[h.childNodes.length-1] );
      };
    };
    
    var raf = ( "undefined" != typeof requestAnimationFrame ) ? requestAnimationFrame : false ||
        ( "undefined" != typeof mozRequestAnimationFrame ) ? mozRequestAnimationFrame : false ||
        ( "undefined" != typeof webkitRequestAnimationFrame ) ? webkitRequestAnimationFrame : false ||
        ( "undefined" != typeof msRequestAnimationFrame ) ? msRequestAnimationFrame : false;
    
    if( raf )
    {
      raf( cb );
    }
    else
    {
      if( "undefined" != typeof window.addEventListener )
        window.addEventListener( 'load', cb );
      else if( "undefined" != typeof window.attachEvent )
        window.attachEvent( 'onload', cb );
    }
    </script>
    

    Thanks to Ultrabenosaurus for the code!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search