LoadCSS: Low-Priority Asynchronous CSS Loading Demo - with CSP support, and no JavaScript fallback

An alternative version of Scott Jehl's new async CSS loader as discussed on Twitter.

LoadCSS Project

This test page demonstrates a new pattern for loading a stylesheet asynchronously at a low priority. The page will turn green when the CSS loads.

Instead of the usual print toggle, this page is loading CSS with rel="alternate stylesheet", which will load async at a low priority. Onload, the rel is set to stylesheet and title is turned off, causing it to apply. What's nice about this pattern is you can add another rel value of "preload" to increase its priority from low to high. View high priority async demo

Scott's solution:


<link rel="alternate stylesheet" href="slow.css" title="styles" as="style" onload="this.title='';this.rel='stylesheet'">

This slight variant uses an external JS file to add the onload via an EventListener to allow it to work with strict Content Security Policy that doesn't allow inline JS on the page. It also adds a <noscript> fallback for when JavaScript is switched off:


<link rel="alternate stylesheet" href="slow.css" title="styles" as="style">
<script src="new-low.js" async></script>
<noscript>
  <link rel="stylesheet" href="slow.css" as="style">
</noscript>

new-low.js contains the following:


var all_head_links = document.querySelectorAll('head > link');
for (index = 0; index < all_head_links.length; ++index) {
  head_link = all_head_links[index]
  if (head_link.rel === "alternate stylesheet") {
    head_link.addEventListener('load',function() {
      this.title = '';
      this.rel = 'stylesheet';
    });
    //Check if the stylesheet is already loaded in case we missed the load event:
    //(uses some "magic": https://stackoverflow.com/a/21147238/2144578)
    if(head_link.sheet && head_link.sheet.cssRules) {
        head_link.title = '';
        head_link.rel = 'stylesheet';
    }
  }
}