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

  • 2
    Are you applying async to styles or scripts? The style loads some time after you load the page or it never appears?
    – kamus
    Sep 24 '15 at 13:17
  • I applied the async attribute to styles and placed them in the header.
    – Paulina994
    Sep 24 '15 at 13:33
  • 2
    The thing with styles is that a re-rendering will be triggered if you load them late (e.g. in the body), and is not allowed in the standards (but since browsers are very forgiving it will work anyway). If the problem is slow response times from a third party server, perhaps you can simply host them on your server instead? Sep 24 '15 at 14:56

11 Answers 11


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. -->

 <!-- 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'">

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.

  • 3
    There's no need to use loadCSS, the polyfill is enough: github.com/filamentgroup/loadCSS/blob/master/src/…
    – nathan
    Aug 12 '18 at 16:48
  • 1
    Preload's spec status is finally [W3C Candidate Recommendation].(w3.org/TR/preload/…) Firefox supports it, but still disabled by default; click on answer's "widely supported" link for "Can I Use's" description of the Firefox flag that controls it. Oct 16 '19 at 11:55
  • 1
    Answer updated to provide solution for full browser support, along with additional explanation. Jan 9 '20 at 12:15
  • 1
    @jabacchetta the 2020 update is very much appreciated, thank you. I was looking specifically for instructions written in recent times where browser support is generally better. A lot changes over 3 years on the web!
    – brandito
    Mar 13 '20 at 4:10
  • 2
    Apparently, it is better to onload="this.rel='stylesheet'; this.onload = null". It is necessary to set this.onload to null to avoid this being called twice in some browsers, apparently.
    – Flimm
    Oct 21 '20 at 10:19

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/

  • Ok.. I didn't know that you can reference element attributes in the on-handlers just by mentioning their name. I always thought 'event' is the only exception.
    – Teemoh
    May 23 '17 at 4:21
  • 1
    So how do you keep your page from flashing as it rerenders everything? Plus do you inline core app shell styles so your page has some initial layout instead of rendering something Lynx would be proud of?
    – Chris Love
    Jan 10 '18 at 18:38
  • 2
    Seems to still work for me. After doing this I know longer get a warning in PageSpeed Insights for this file.
    – AndyWarren
    Mar 16 '18 at 19:13
  • 3
    this is working for me (08-july -2018) . And it giving good score in pagespeed insight Jul 8 '18 at 7:28
  • 1
    IMHO, jabachetta's newer answer using "preload", is likely the preferred solution now. If anyone has a reason to think this answer is still preferable, please add a comment explaining why. Ideally linking to a resource that confirms why/when this approach still might be preferable. [Assuming you use the polyfill to support preload on Firefox and on older browsers - see link in first comment of that answer]. Oct 16 '19 at 12:18

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:

  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.


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

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

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

2.Inserting DOM in the old way

<script type="text/javascript">
  var bsa = document.createElement('script');
     bsa.type = 'text/javascript';
     bsa.async = true;
     bsa.src = 'https://s3.buysellads.com/ac/bsa.js';

3.if you can try plugins you could try loadCSS

  // include loadCSS here...
  function loadCSS( href, before, media ){ ... }
  // load a file
  loadCSS( "path/to/mystylesheet.css" );
  • 3
    Example 2 loads Javascript, but the question is about loading CSS. Do you know if example 2 works also for CSS, if you change from <script> to <style rel=stylesheet>? (Just curious. I'm going to use loadCSS (i.e. your example 3) instead, if I need to load CSS later.)
    – KajMagnus
    Sep 4 '17 at 14:36

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 = [

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

window.addEventListener('load', loadAsyncStyleSheets, false);
  • 1
    Are there any drawbacks of this method if we compare it say with the loadCSS approach? It seems, the classical code var newStyle = document.createElement("link"); newStyle.rel = "stylesheet"; newStyle.href = "stylesheet.css"; document.getElementsByTagName("head")[0].appendChild(newStyle); inside the <script> tag in the page body does its work excellently - even in old browsers like MSIE8.
    – TecMan
    Apr 23 '18 at 13:22
  • 2
    @TecMan yes there are. As you can see, this function does it's job on window.load event. So, download starts when everything is downloaded. No luck there. You need non blocking loading as soon as possible to start. Nov 13 '18 at 13:17

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'">

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);

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")

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 think the async attribute is ignored, as the script tag does not have a src to load asynchronously... or is it really useful here? Also can you elaborate a bit more on which value to use as a nonce?
    – Philipp
    Sep 5 '18 at 11:14

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" >
    < /noscript >

  var loadDeferredStyles = function() {
    var addStylesNode = document.getElementById("deferred-styles");
    var replacement = document.createElement("div");
    replacement.innerHTML = addStylesNode.textContent;
  var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
      window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
  else window.addEventListener('load', loadDeferredStyles);
  • 1
    Likely a false positive (PageSpeed bug) if you're using the preload keyword approach I mentioned. github.com/filamentgroup/loadCSS/issues/53 Jun 26 '18 at 15:30
  • 1
    UPDATE: Google has deprecated, and then shutdown, PageSpeed version 4 that had this problem - that was the version for which this async code was recommended. Although I haven't tested in PageSpeed 5: given the description of how they test now, and their support for "preload" tag of "link", jabachetta's answer is likely a better answer now, for Google. Oct 16 '19 at 12:13
  • 1
    @ToolmakerSteve Yes This answer needs to be moderated often. But this code still works to get you a 100 in Page Speed. Oct 31 '19 at 6:37

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?

  • I am looking for the same, Had you got something :D Jun 21 at 10:39

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'">

Your Answer

