Load CSS Files Asynchronously For Better Performance
June 23, 2020 by Andreas Wik
I just read a really interesting article on Smashing Magazine about what we can do for performance on the web, specifically for people with slower connections and limited data plans. Definitely worth a read if you got some time to spare.
A cool trick they brought up was this…
We want a meaningful paint as quickly as possible and minimize the wait for the user to see something on the screen. Placing critical CSS (and by critical I mean CSS that’s necessary to make the first visible portion of the page (stuff in the viewport without scrolling) look decent) inline, rather than in its own file, is a quick and great little trick many of us use. No need to wait for a request of a CSS file to finish before these styles can be applied to the page.
Then what about the “non critical” CSS files? The rest of the stuff further down on the page, third party plugin CSS files etc… You would put those in <link> tags in the <head>.
The annoying thing here is that by default browsers will not start rendering the page until these files in the <head> have been downloaded and parsed.
How could we load the CSS files in the background, asynchronously?
The usual, synchronous, way to include a CSS file is something like this:
<link href="styles.css" rel="stylesheet" media="all" />
Maybe you don’t set the media attribute, which is fine. It would default to all, meaning the stylesheet will be loaded and used for all devices and modes.
What if we set it to print instead? This would tell the browser to only apply the styles when the user is in print mode. Since the user won’t be in print mode, the browser won’t prioritize this file, and actually just load it in the background (asynchronously), NOT stalling the rendering of the page.
However, one more thing is needed. Once the file has been loaded, we still want to apply it to all media. So let’s use the onload attribute to change the media to all or screen.
<link href="extra-styles.css" rel="stylesheet" media="print" onload="this.media='all'" />
This works great!
For all the details of different values for the media attribute and more on the link tag, head over to Mozilla: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link