-
Notifications
You must be signed in to change notification settings - Fork 37
Implement Asynchronous CSS #199
Description
Is your enhancement related to a problem? Please describe.
One of the main pain points of the link tag is that it cannot be loaded asynchronously using async or defer - in order ensure that big CSS files, or even third party CSS files can be loaded asynchronously we should look at ways to load CSS more dynamically.
Describe the solution you'd like
We have a hook built into the theme-scaffold called script_loader_tag which helps us load script-based assets with async and defer - I'd like to suggest a similiar hook, but one that only focuses on styles. Essentially any tagged styles should be loaded as such:
<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">
The methodology of this technique is explained under "Additional Context" in more detail below, but the TL;DR of it is:
- By loading a
stylesheetwithmedia="print"by default, the browser loads the CSS without render-blocking the page. - Because
printdoes not actually apply styles by default in the browser, we need to ensure that we set this media toallonce theDOMis ready, hence theonloadattribute rewriting themediaattribute toallonce theDocumentis ready.
Its a clean and non-render blocking approach to get CSS to load asynchronously.
This approach can also be achieved using rel="preload" and updating it to rel="stylesheet" on document.ready but not all browser vendors support rel="preload" at this point.
Describe alternatives you've considered
- We could look at implementing the CriticalCSS model, however, this comes with serious drawbacks to implement manually. @Firestorm980 and I had a discussion regarding CriticalCSS where the content above the fold is very dynamic (for instance including widgets) and the model starts to breakdown a bit.
- loadCSS is another way of doing this: https://github.com/filamentgroup/loadCSS - however it has a very heavily requirement on JavaScript and if it any other script halts execution we could be in for a mess.
Additional context