Skip to content
This repository has been archived by the owner on May 2, 2022. It is now read-only.

Implement Asynchronous CSS #199

Open
dainemawer opened this issue Sep 14, 2020 · 8 comments
Open

Implement Asynchronous CSS #199

dainemawer opened this issue Sep 14, 2020 · 8 comments

Comments

@dainemawer
Copy link
Contributor

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 stylesheet with media="print" by default, the browser loads the CSS without render-blocking the page.
  • Because print does not actually apply styles by default in the browser, we need to ensure that we set this media to all once the DOM is ready, hence the onload attribute rewriting the media attribute to all once the Document is 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

@samikeijonen
Copy link
Contributor

Plus one from me. I have also used this technique myself.

@ryansommers
Copy link
Contributor

@dainemawer I haven't done this personally but it sounds like a good strategy.

@Firestorm980
Copy link
Contributor

@dainemawer I think it is a good idea for a feature to include. I wonder if there are any issues going forward with the lock-in associated with it? Probably a bigger discussion of critical CSS.

@smy315
Copy link
Contributor

smy315 commented Sep 22, 2020

Should we include a fallback when JS is disabled? With this approach, CSS will not load if JS is disabled. So something like this?

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

<noscript>
  <link rel="stylesheet" href="/path/to/my.css" media="screen">
</noscript>

@dainemawer
Copy link
Contributor Author

dainemawer commented Sep 25, 2020

@smy315 yup I like that idea!

@jeffpaul
Copy link
Member

@dainemawer want to work up a PR for this?

@dainemawer
Copy link
Contributor Author

@jeffpaul yes sir - we'll get something up tomorrow!

@dainemawer
Copy link
Contributor Author

@jeffpaul looks like I don't have write access to the repo - could you update my permissions?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants