Skip to content

Instantly share code, notes, and snippets.

@scottjehl
Last active August 12, 2023 16:57
Show Gist options
  • Save scottjehl/87176715419617ae6994 to your computer and use it in GitHub Desktop.
Save scottjehl/87176715419617ae6994 to your computer and use it in GitHub Desktop.
Comparing two ways to load non-critical CSS

I wanted to figure out the fastest way to load non-critical CSS so that the impact on initial page drawing is minimal.

TL;DR: Here's the solution I ended up with: https://github.com/filamentgroup/loadCSS/


For async JavaScript file requests, we have the async attribute to make this easy, but CSS file requests have no similar standard mechanism (at least, none that will still apply the CSS after loading - here are some async CSS loading conditions that do apply when CSS is inapplicable to media: https://gist.github.com/igrigorik/2935269#file-notes-md ).

Seems there are a couple ways to load and apply a CSS file in a non-blocking manner:

  • A) Use an ordinary link element to reference the stylesheet, and place it at the end of the HTML document, after all the content. (This is what Google recommends here https://developers.google.com/speed/docs/insights/PrioritizeVisibleContent )
  • B) Fetch it asynchronously with some inline JavaScript from the head of the page, by appending a link element to page dynamically. (To ensure it's async, I'm setting the link's media to a non-applicable media query, then toggling it back after the request goes out).

I suspected B would initiate the request sooner, since A would be dependent on the size of the content in the document - parsing it in entireity before kicking off the request.

In this case, sooner would be ideal to reduce impact on our page load process, since there could be minor reflows that are triggered by the styles in the non-critical CSS file (ideally, the critical CSS would have all reflow-triggering styles in it, but that so far, that's been hard to pull off across the breakpoints of a responsive design, and given that the initial inlined CSS should be kept very small to fit into the first round trip from the server).

I made some test pages, and they do seem to confirm that B will load the CSS sooner (B requests the css file after around 60-70ms whereas A usually requests it around 130-200ms). It's consistently about twice as fast.

B comes with the additional benefits of qualifying the request based on whatever conditions we care to test too, which is nice.

Copy link

ghost commented Mar 6, 2017

I've developed and open sourced a new approach to handling asynchronous CSS and JS so I could use PhotoSwipe on my new blog. I hope you like it: https://www.npmjs.com/package/fetch-inject.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment