Deferring CSS load for unmatched Media Queries

I'd like to raise again some previously raised concerns regarding
loading of unnecessary CSS files.
In a previous thread [1], Henri Sivonen raised a concern that current CSS
loading behavior, and specifically the loading of unnecessary CSS files
(that their `media` attributes suggest they are not required) may result in
authors using JavaScript-based CSS loading or none-markup means in order to
avoid their loading.

A few recent examples of such JS based mechanisms are eCSSential [2], and
Mozilla's Chris Heilmann's blog post [3].
They were followed by criticism for the downsides of that approach [4][5]

Tab Atkins proposed [6] using the `async` attribute to signify:
* That a CSS file's CSSOM will not be inspected by JS before a JS call will
explicitly request it to be loaded
* That a CSS file is not required to be loaded at all until explicitly
  requested using a JS call.

While this proposal enables authors to avoid loading of unnecessary CSS
in some cases, I'm afraid it does not resolve the main use-case in
which authors would like their CSS files not loaded.

I like to call this case the "Essential CSS unless it doesn't match current
viewport" case.

Consider the following code sample:
   <!-- High priority CSS. should be loaded before paint for all viewport
sizes -->
   <link href="common_for_all_breakpoints.css" rel="stylesheet"
media="screen">
   <!-- High priority CSSes for the relevant viewport. The one which media
matches is needed as close as possible to first paint. The others can be
deferred, possibly forever -->
   <link href="small_screen.css" rel="stylesheet" media="screen and
(max-width: 599px)">
   <link href="medium_screen.css" rel="stylesheet" media="screen and
(min-width: 600px and max-width: 899px)">
   <link href="large_screen.css" rel="stylesheet" media="screen and
(min-width: 900px)">
   <!-- Low priority CSS. Need to be loaded if JS brings in content that
needs it. -->
   <link href="lazy_loaded_content.css" rel="stylesheet" media="screen">
   <!-- Low priority CSS that can be deferred, possibly forever, unless the
user actually prints -->
   <link href="print.css" rel="stylesheet" media="print">

`async` will enable authors to postpone the loading of
 "lazy_loaded_content.css".
It will not enable authors to signify the browser that a certain CSS must
be loaded only when and as soon as its media query matches, which is what
needed for the 3 viewport specific CSS files, as well as for the print one.
Using `async` on any of these CSS files will result in FOUC, and will
create a JS dependency if authors actually want that these styles will
affect the page.

Since lazy loaded content can in most cases dynamically load its own
CSS, I think that the current definition of the proposed `async` (at
least as far as I understand it) does not respond to the largest use
case of deferred CSS loading.

In my opinion an `onmatch` attribute (or any other name) can signify the
browser that no JS inspects that CSS's CSSOM unless its media matches and
it was in fact loaded (a callback mechanism, similar to the one proposed
for `async` can then be used).
The main difference of that attribute and `async` would be that in case
that the media attribute does match (including the default screen attribute
value), the CSS is considered essential (same as a regular CSS today) and
is loaded before first paint (in browsers that do that).

I'm not sure if there is a place for such an attribute alongside `async`
or instead of it. But I do believe that `async` alone, as defined, is
not the answer authors are hoping for.

Thanks,
Yoav

[1] http://lists.w3.org/Archives/Public/www-style/2013Jan/0434.html
[2] https://github.com/scottjehl/eCSSential
[3]
http://christianheilmann.com/2012/12/19/conditional-loading-of-resources-with-mediaqueries/
[4]
http://www.igvita.com/2012/06/14/debunking-responsive-css-performance-myths/
[5]
http://andydavies.me/blog/2012/12/29/think-twice-before-using-matchmedia-to-conditionally-load-stylesheets/

Received on Monday, 4 February 2013 17:09:37 UTC