A recent blink-dev intent and ensuing discussion got me thinking about the current ways we load styles.
This was heavily discussed in the past (#1, #2), but those discussions seemed focused on one case, where I think we can benefit from a more holistic discussion.
AFAIU, we have a few different cases for styles loaded today:
- Critical CSS - required for the page’s initial rendering. Should block rendering.
- Non-critical CSS - needed for the current page’s hidden parts. May or may not need to block the rendering of those hidden parts.
- Non-matching CSS - not required for current page unless conditions change. (e.g. print)
(1) is implemented through regular style links today, and currently (at least in Chromium), blocks the rendering, but not the HTML’s parsing. One side effect of that is that async scripts defined after the style (with no blocking scripts in the way) can still execute before the stylesheet finished downloading, enabling interesting loading patterns. The intent above wants to change that, in order to reduce code complexity, but at the expense of those patterns.
(2) can be implemented in multiple ways. One such way is to have the style links be embedded in the body, right above the content which they impact. Another is to use script-driven CSS loading patterns. Those 2 approaches have different characteristics. The former blocks the parser (at least in Chromium[1]), meaning that async scripts defined after it will not run before it finished loading. On the other hand, it also means that it will block rendering of everything below it. The latter approach doesn’t impact rendering at all, until the style finished loading, so can result in FOUC, but on the other hand, might be faster, as parsing is not paused.
Seems like it would be good to document:
- The use-cases for running async scripts while styles are loading
- If it’s just for timing out blocking styles, maybe we can come up with a better API
- The use-cases for non-critical styles that shouldn’t block rendering at all
- AFAICT, that’s the use case for deferred stylesheets beyond the current in-body behavior, but it’s not clear to me what it is…
[1] Browsers disagree on many things related to style loading. It would be good to try and coalesce behaviors here, but that may be a tangent.