[html] How to load CSS Asynchronously

I'm trying to eliminate 2 CSS files that are render blocking on my site - they appear on Google Page Speed Insights. I have followed different methods, none of which were a success. But, recently, I found a post about Thinking Async and when I applied this code: <script async src="https://third-party.com/resource.js"></script>it did eliminate the problem.

However, after publishing, the page lost the styling. I'm not too sure as to what is going on because the code works but it's the styling after upload that doesn't work. Would appreciate your help with this. Thanks

This question is related to html css asynchronous

The answer is


Using media="print" and onload

The filament group recently (July 2019) published an article giving their latest recommendation for how to load CSS asynchronously. Even though they are the developers of the popular Javascript library loadCSS, they actually recommend this solution that does not require a Javascript library:

<link
  rel="stylesheet"
  href="/path/to/my.css"
  media="print"
  onload="this.media='all'; this.onload = null"
>

Using media="print" will indicate to the browser not to use this stylesheet on screens, but on print. Browsers actually do download these print stylesheets, but asynchronously, which is what we want. We also want the stylesheet to be used once it is downloaded, and for that we set onload="this.media='all'; this.onload = null". (Some browser will call onload twice, to work around that, we need to set this.onload = null.) If you want, you can add a <noscript> fallback for the rare users who don't have Javascript enabled.

The original article is worth a read, as it goes into more detail than I am here. This article on csswizardry.com is also worth a read.


2020 Update


The simple answer (full browser support):

<link rel="stylesheet" href="style.css" media="print" onload="this.media='all'">

The documented answer (with optional preloading and script-disabled fallback):

 <!-- Optional, if we want the stylesheet to get preloaded. Note that this line causes stylesheet to get downloaded, but not applied to the page. Use strategically — while preloading will push this resource up the priority list, it may cause more important resources to be pushed down the priority list. This may not be the desired effect for non-critical CSS, depending on other resources your app needs. -->
 <link rel="preload" href="style.css" as="style">

 <!-- Media type (print) doesn't match the current environment, so browser decides it's not that important and loads the stylesheet asynchronously (without delaying page rendering). On load, we change media type so that the stylesheet gets applied to screens. -->
 <link rel="stylesheet" href="style.css" media="print" onload="this.media='all'">

 <!-- Fallback that only gets inserted when JavaScript is disabled, in which case we can't load CSS asynchronously. -->
 <noscript><link rel="stylesheet" href="style.css"></noscript>

Preloading and async combined:

If you need preloaded and async CSS, this solution simply combines two lines from the documented answer above, making it slightly cleaner. But this won't work in Firefox until they support the preload keyword. And again, as detailed in the documented answer above, preloading may not actually be beneficial.

<link href="style.css" rel="preload" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="style.css"></noscript>

Additional considerations:

Note that, in general, if you're going to load CSS asynchronously, it's generally recommended that you inline critical CSS, since CSS is a render-blocking resource for a reason.

Credit to filament group for their many async CSS solutions.


Please care to update the answer as all of the above fails to impress google pagespeed insights now.

According to Google this is how you should implement async loading of Css

 < noscript id="deferred-styles" >
        < link rel="stylesheet" type="text/css" href="small.css"/ >
    < /noscript >

<script>
  var loadDeferredStyles = function() {
    var addStylesNode = document.getElementById("deferred-styles");
    var replacement = document.createElement("div");
    replacement.innerHTML = addStylesNode.textContent;
    document.body.appendChild(replacement)
    addStylesNode.parentElement.removeChild(addStylesNode);
  };
  var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
      window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
  if (raf) raf(function() { window.setTimeout(loadDeferredStyles, 0); });
  else window.addEventListener('load', loadDeferredStyles);
</script>

The trick to triggering an asynchronous stylesheet download is to use a <link> element and set an invalid value for the media attribute (I'm using media="none", but any value will do). When a media query evaluates to false, the browser will still download the stylesheet, but it won't wait for the content to be available before rendering the page.

<link rel="stylesheet" href="css.css" media="none">

Once the stylesheet has finished downloading the media attribute must be set to a valid value so the style rules will be applied to the document. The onload event is used to switch the media property to all:

<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'">

This method of loading CSS will deliver useable content to visitors much quicker than the standard approach. Critical CSS can still be served with the usual blocking approach (or you can inline it for ultimate performance) and non-critical styles can be progressively downloaded and applied later in the parsing / rendering process.

This technique uses JavaScript, but you can cater for non-JavaScript browsers by wrapping the equivalent blocking <link> elements in a <noscript> element:

<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'"><noscript><link rel="stylesheet" href="css.css"></noscript>

You can see the operation in www.itcha.edu.sv

enter image description here

Source in http://keithclark.co.uk/


Use rel="preload" to make it download independently, then use onload="this.rel='stylesheet'" to apply it to the stylesheet (as="style" is necessary to apply it to stylesheet else the onload won't work)

<link rel="preload" as="style" type="text/css" href="mystyles.css" onload="this.rel='stylesheet'">

If you have a strict content security policy that doesn't allow @vladimir-salguero's answer, you can use this (please make note of the script nonce):

<script nonce="(your nonce)" async>
$(document).ready(function() {
    $('link[media="none"]').each(function(a, t) {
        var n = $(this).attr("data-async"),
            i = $(this);
        void 0 !== n && !1 !== n && ("true" == n || n) && i.attr("media", "all")
    })
});
</script>

Just add the following to your stylesheet reference: media="none" data-async="true". Here's an example:

<link rel="stylesheet" href="../path/script.js" media="none" data-async="true" />

Example for jQuery:

<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css" type="text/css" media="none" data-async="true" crossorigin="anonymous" /><noscript><link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css" type="text/css" /></noscript>

I have try to use:

<link rel="preload stylesheet" href="mystyles.css" as="style">

It works fines, but It also raises cumulative layout shift because when we use rel="preload", it just download css , not apply immediate.

Example when the DOM load a list contains ul, li tags, there is an bullets before li tags by default, then CSS applied that I remove these bullets to custom styles for listing. So that, the cumulative layout shift is happening here.

Is there any solution for that?


The function below will create and add to the document all the stylesheets that you wish to load asynchronously. (But, thanks to the Event Listener, it will only do so after all the window's other resources have loaded.)

See the following:

function loadAsyncStyleSheets() {

    var asyncStyleSheets = [
    '/stylesheets/async-stylesheet-1.css',
    '/stylesheets/async-stylesheet-2.css'
    ];

    for (var i = 0; i < asyncStyleSheets.length; i++) {
        var link = document.createElement('link');
        link.setAttribute('rel', 'stylesheet');
        link.setAttribute('href', asyncStyleSheets[i]);
        document.head.appendChild(link);
    }
}

window.addEventListener('load', loadAsyncStyleSheets, false);

If you need to programmatically and asynchronously load a CSS link:

// https://www.filamentgroup.com/lab/load-css-simpler/
function loadCSS(href, position) {
  const link = document.createElement('link');
  link.media = 'print';
  link.rel = 'stylesheet';
  link.href = href;
  link.onload = () => { link.media = 'all'; };
  position.parentNode.insertBefore(link, position);
}

you can try to get it in a lot of ways :

1.Using media="bogus" and a <link> at the foot

<head>
    <!-- unimportant nonsense -->
    <link rel="stylesheet" href="style.css" media="bogus">
</head>
<body>
    <!-- other unimportant nonsense, such as content -->
    <link rel="stylesheet" href="style.css">
</body>

2.Inserting DOM in the old way

<script type="text/javascript">
(function(){
  var bsa = document.createElement('script');
     bsa.type = 'text/javascript';
     bsa.async = true;
     bsa.src = 'https://s3.buysellads.com/ac/bsa.js';
  (document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(bsa);
})();
</script>

3.if you can try plugins you could try loadCSS

<script>
  // include loadCSS here...
  function loadCSS( href, before, media ){ ... }
  // load a file
  loadCSS( "path/to/mystylesheet.css" );
</script>

Async CSS Loading Approaches

there are several ways to make a browser load CSS asynchronously, though none are quite as simple as you might expect.

<link rel="preload" href="mystyles.css" as="style" onload="this.rel='stylesheet'">

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to asynchronous

How to read file with async/await properly? Use Async/Await with Axios in React.js Waiting until the task finishes How to reject in async/await syntax? React - Display loading screen while DOM is rendering? angular 2 how to return data from subscribe How do I access store state in React Redux? SyntaxError: Unexpected token function - Async Await Nodejs Why does .json() return a promise? Why is setState in reactjs Async instead of Sync?