Re: [whatwg] Proposal for change in recommendation for loading behavior of non-applicable stylesheets

2012-08-28 Thread Ian Hickson
On Sun, 10 Jun 2012, Scott Jehl wrote:
 
 CSS referenced by link elements or @import has always come with the 
 limitation that it will block page rendering until it has finished 
 loading.

Not always, actually. In theory, it's not necessary. Originally, the 
blocking was added to avoid flashes of unstyled content (FoUCs). Later, it 
turned out scripts relied on this blocking in their computations, which 
rather forced the issue.


 However, the downside of this behavior is that ALL CSS, not just the CSS 
 that will apply to the particular device and viewport at the time of 
 page load, will block page rendering. This means that sites that use 
 CSS3 media queries to deliver different styles to different browsing 
 conditions will be delivering more and more overhead.

Given the size of CSS sheets, I don't think that's a huge deal. It's 
already possible to merge all one's sheets into a single gzip-compressed 
file, at which point the bulk of the slowdown is in the latency, not the 
bandwidth. (That is, the time from the page being received to the first 
byte of the style sheet being received will vastly overwhelm the time 
between the first byte and the last byte of the style sheet.)


 Recently, I did some research into how browsers request CSS files via 
 link elements with inapplicable media queries. The results were grim. Of 
 all browsers that I tested, every one would not only request all CSS 
 files referenced with inapplicable media types/queries, but they would 
 also block the rendering of page content until all of those inapplicable 
 styles were loaded.
 
 Here's the test page including a table with the test results: 
 http://scottjehl.github.com/CSS-Download-Tests/

Part of the problem is that the style sheets are supposed to be exposed to 
the DOM, which is detectable from script. So you have to block before 
script executes. You can work around this a bit by putting your scripts 
first. (In general, the less you observe what the browser is doing, the 
cleverer it can be. This makes testing a bit difficult...)


 Proposal for change:
 
 I'd like to propose that the spec recommends that vendors defer the 
 loading of Stylesheets referenced via inapplicable media so that they do 
 not block page rendering.

Unfortunately this is not Web-compatible, as I understand it, because it 
affects how they are exposed in the DOM.


We could add a feature that prevents blocking on a style sheet if the 
media query doesn't apply, I guess, if there's implementor interest. I 
recommend seeing if any vendor is interested in experimenting with this.


 2. Reducing the amount of time that an unresponsive stylesheet can block 
 page rendering
 
 One last suggestion. In the research above, I found that many modern 
 browsers will prevent page rendering for upwards of 30 seconds 
 (sometimes more) to ensure that all stylesheets have loaded. If a server 
 is not responding for some reason, this results in a completely unusable 
 experience.

Blocking scripts when waiting for a style sheet is required by the 
specification, but blocking rendering is not. This is a quality-of- 
implementation issue.


On Sun, 10 Jun 2012, Scott Jehl wrote:
 
 That said, merely deferring the load of stylesheets that don't apply at 
 initial load would be a huge performance improvement for users.

Are you sure? In high-bandwidth, high-latency situations, this seems 
highly unlikely. (I agree that it could be true in low-bandwidth, 
low-latency situations, but those are much rarer.) The round-trip time 
will often far outweigh the download time, and multiple requests can be 
made in parallel, not blocking on each other. If it takes 10 seconds to 
get a file, and each file fits in a single TCP packet, then you could 
download one file or six files and it would in either case take 10 
seconds. Not loading them would have no client-side-visible difference.


On Sun, 10 Jun 2012, Boris Zbarsky wrote:

 E.g. nothing in the spec actually has any requirements at all on 
 starting rendering.

Actually technically the spec requires that rendering happen when the 
event loop spins. :-)


On Mon, 11 Jun 2012, Boris Zbarsky wrote:
  
  I think you've rightfully pointed out that the lazy-loading idea 
  probably won't fly with vendors and could even cause problems in 
  certain cases.
 
 I think it would be quite doable and the spec should be changed to allow 
 it. I'm just not sure that the spec should _require_ it in all cases, 
 because we can end up in situations where simply detecting whether 
 something should be lazy-loaded or not is more expensive than just 
 loading it.

The spec doesn't require any network loads to be done in finite time, 
which essentially allows lazy loading. (The only requirement is that 
scripts block if there's style sheets that could affect them.)

The spec also says, specifically for link resources, that:

# User agents may opt to only try to obtain such resources when they are
# needed, instead of pro-actively 

Re: [whatwg] Proposal for change in recommendation for loading behavior of non-applicable stylesheets

2012-06-20 Thread Andy Davies
Doesn't this section of the HTML spec already allow for what Scott wants:

http://www.whatwg.org/specs/web-apps/current-work/#the-link-element

For external resources that are represented in the DOM (for example,
style sheets), the DOM representation must be made available even if
the resource is not applied. To obtain the resource, the user agent
must run the following steps:

If the href attribute's value is the empty string, then abort these steps.

Resolve the URL given by the href attribute, relative to the element.

If the previous step fails, then abort these steps.

Fetch the resulting absolute URL.

User agents may opt to only try to obtain such resources when they are
needed, instead of pro-actively fetching all the external resources
that are not applied.

Looking at waterfalls for a page loading Android 2.3 and iOS 5, it
appears that iOS does defer the non-applicable stylesheets - question
is why don't more browsers?

iOS 5 - http://www.blaze.io/mobile/result/?testid=120615_J6_927
Android 2.3 - http://www.blaze.io/mobile/result/?testid=120615_2D_929

Cheers

Andy


Re: [whatwg] Proposal for change in recommendation for loading behavior of non-applicable stylesheets

2012-06-20 Thread Boris Zbarsky

On 6/20/12 3:16 PM, Andy Davies wrote:

Looking at waterfalls for a page loading Android 2.3 and iOS 5, it
appears that iOS does defer the non-applicable stylesheets - question
is why don't more browsers?


In Gecko's case it's as I said: stylesheet loads are often kicked off 
before media query information is available...  We could probably 
redesign stylesheet loading to make it happen somewhat later or maybe 
redesign pageload to get media query information earlier, but it just 
hasn't happened yet.


-Boris


Re: [whatwg] Proposal for change in recommendation for loading behavior of non-applicable stylesheets

2012-06-20 Thread Scott Jehl
That'd be really great if Moz did head in that direction.

Here's a post from one of the Webkit devs on how it works internally for that 
platform.

http://www.igvita.com/2012/06/14/debunking-responsive-css-performance-myths/


On Jun 20, 2012, at 5:02 PM, Boris Zbarsky wrote:

 On 6/20/12 3:16 PM, Andy Davies wrote:
 Looking at waterfalls for a page loading Android 2.3 and iOS 5, it
 appears that iOS does defer the non-applicable stylesheets - question
 is why don't more browsers?
 
 In Gecko's case it's as I said: stylesheet loads are often kicked off before 
 media query information is available...  We could probably redesign 
 stylesheet loading to make it happen somewhat later or maybe redesign 
 pageload to get media query information earlier, but it just hasn't happened 
 yet.
 
 -Boris



Re: [whatwg] Proposal for change in recommendation for loading behavior of non-applicable stylesheets

2012-06-11 Thread Scott Jehl
Thanks again, Boris.

These are fair answers, but I can't help but think that the problem is critical 
enough to warrant spec-level consideration. 

As device contexts are increasing, authors are referencing more stylesheets to 
address them, and the existing behavior across most browsers ensures that every 
last byte of those stylesheets will be loaded - often in a synchronous/blocking 
manner. This is less about author convenience and more of a benefit to users: 
deferring the load of inapplicable stylesheets would surely have a large impact 
on perceived page performance. I'd be happy to provide some demos of existing 
sites with my shim included for profiling sake.

Further, judging by the response received on twitter when I posted that 
research last week, I think the current behavior is not at all what most 
authors expect to happen. But we also don't really have any other options aside 
from using JavaScript to make it work the way it seems like it really should. 

I think you've rightfully pointed out that the lazy-loading idea probably won't 
fly with vendors and could even cause problems in certain cases.  In the past, 
there were similar concerns for @media print stylesheets, which are always 
requested (like all other non-applicable media) up-front, perhaps in the 
off-chance that connectivity would be lost when the user tries to print. That's 
at least the reasoning I'd seen cited before, and that behavior led to authors 
embedding @media print styles inside their @media all stylesheet just to 
prevent that HTTP overhead.

Unfortunately, these days inlining every media query does nothing to solve this 
problem, aside from reducing HTTP requests by shifting all our weight into a 
single heavy request.

Even assuming that implementing this feature would mean delaying CSS 
prefetching until the metaviewport tag was parsed, wouldn't the tradeoff in 
page loading speed be worth it? I'd imagine many pages could have several fewer 
blocking requests as a result.

Thanks again and if you feel this isn't the proper forum for addressing this 
issue, do you have any suggestions where I should take it?

Scott

Re: [whatwg] Proposal for change in recommendation for loading behavior of non-applicable stylesheets

2012-06-11 Thread Boris Zbarsky

On 6/10/12 11:26 PM, Scott Jehl wrote:
 These are fair answers, but I can't help but think that the problem
 is critical enough to warrant spec-level consideration.

Oh, yes.  The question is how to spec this in a way that doesn't 
overconstrain future implementations to behave suboptimally.


 I think you've rightfully pointed out that the lazy-loading idea
 probably won't fly with vendors and could even cause problems in
 certain cases.

I think it would be quite doable and the spec should be changed to allow 
it.  I'm just not sure that the spec should _require_ it in all cases, 
because we can end up in situations where simply detecting whether 
something should be lazy-loaded or not is more expensive than just 
loading it.


 Even assuming that implementing this feature would mean delaying CSS
 prefetching until the metaviewport tag was parsed, wouldn't the
 tradeoff in page loading speed be worth it?

It depends on the use cases  Consider a page that has no meta 
viewport at all (i.e. most of them).  Your proposed change right above 
would disable CSS prefetching altogether on such a page, which is pretty 
undesirable.


 Thanks again and if you feel this isn't the proper forum for
 addressing this issue, do you have any suggestions where I should
 take it?

This list is the right forum.

-Boris



[whatwg] Proposal for change in recommendation for loading behavior of non-applicable stylesheets

2012-06-10 Thread Scott Jehl
Hello.

This is a proposal for an addition to the LINK element spec that includes a 
recommendation for deferring the load of inapplicable stylesheets until later 
in the load process (thus not blocking page rendering for unnecessary styles).

Some background:

CSS referenced by link elements or @import has always come with the limitation 
that it will block page rendering until it has finished loading. In many cases, 
there's good reason for this behavior, as the alternative - simply letting the 
page render independently of stylesheet requests -- almost always results in a 
flash of unstyled content. However, the downside of this behavior is that ALL 
CSS, not just the CSS that will apply to the particular device and viewport at 
the time of page load, will block page rendering. This means that sites that 
use CSS3 media queries to deliver different styles to different browsing 
conditions will be delivering more and more overhead.

Recently, I did some research into how browsers request CSS files via link 
elements with inapplicable media queries. The results were grim. Of all 
browsers that I tested, every one would not only request all CSS files 
referenced with inapplicable media types/queries, but they would also block the 
rendering of page content until all of those inapplicable styles were loaded.

Here's the test page including a table with the test results:
http://scottjehl.github.com/CSS-Download-Tests/


Proposal for change:

I'd like to propose that the spec recommends that vendors defer the loading of 
Stylesheets referenced via inapplicable media so that they do not block page 
rendering. These stylesheets should probably still be requested asynchronously 
so that they are present in the event that their media becomes active (say, 
after a browser resize or orientation change), but loading them up-front slows 
down the user experience unnecessarily.


Example implementation of proposed behavior:

Following the research above, I created a JavaScript utility that causes 
browsers to load CSS in a blocking or asynchronous manner, depending on their 
need at load time. I'm not a fan of using JavaScript to do something like this 
unless we have to, but for the time being, I think it illustrates the 
advantages of the proposed behavior. The project readme explains further and 
includes demo files that log information about what files where loaded, and 
how, depending on device and viewport conditions: 
https://github.com/scottjehl/eCSSential#readme

One very common case that this unfortunately can never solve is preventing the 
request of inapplicable styles that are concatenated into a single CSS file. 
The workaround above addresses this scenario though, and if link fetching 
behavior was improved in the ways suggested above, a workaround that works with 
concatenated files would at least be easier to produce.


-- FURTHER SUGGESTIONS --

1. Entirely preventing the request of stylesheets that may never apply

It would be ideal if a device could completely restrict the download of 
stylesheets that it determines could never apply within its environment. For 
example, if a stylesheet is referenced using a (min-width: 1000px) media query, 
a small-screen device could decide that this stylesheet should not be fetched 
at all because it could never apply on its screen dimensions.  This is actually 
the default behavior implemented by the eCSSential workaround above for min and 
max height/width queries. It merely re-evaluates if an inapplicable query would 
apply if it were a device query instead of a viewport query, and if not, the 
stylesheet is not loaded at all. 

The savings in HTTP weight and request counts as a result of this change can be 
very significant on a small screen. Of course, this behavior runs the risk of 
not having a stylesheet on-hand when the browser is moved to another screen. 

With this edge case in mind, it would be ideal if stylesheets that could not 
apply on a particular device are ONLY requested in the event that their media 
conditions become true. In other words, if device conditions changed to make a 
media query apply, such as moving the browser window to another screen, the 
necessary stylesheets would be requested at that time.



2. Reducing the amount of time that an unresponsive stylesheet can block page 
rendering

One last suggestion. In the research above, I found that many modern browsers 
will prevent page rendering for upwards of 30 seconds (sometimes more) to 
ensure that all stylesheets have loaded. If a server is not responding for some 
reason, this results in a completely unusable experience.

I'd like to propose that the spec recommends that stylesheets be given a 
timeout of a much lower maximum before rendering the page in whatever state it 
happens to be in. Ideally, the responsive requests would be left open or 
restarted so that they're given a chance to load and apply after the content is 
shown, but they should not block page rendering 

Re: [whatwg] Proposal for change in recommendation for loading behavior of non-applicable stylesheets

2012-06-10 Thread Boris Zbarsky

On 6/10/12 12:51 PM, Scott Jehl wrote:

I'd like to propose that the spec recommends that vendors defer the
loading of Stylesheets referenced via inapplicable media so that they
do not block page rendering.


One issue with this is that in many cases the UA may not yet know what
media queries apply to the document when starting the sheet loads.  In
some cases it does, of course, but those may be rarer than you think...


For example, if a stylesheet is referenced using a
(min-width: 1000px) media query, a small-screen device could decide
that this stylesheet should not be fetched at all because it could
never apply on its screen dimensions.


Actually, it could, because the media query applies to viewport 
dimensions (in CSS pixels), not screen dimensions.  A trivial example 
would be this document:


  !DOCTYPE html
  iframe style=width: 2000px
  src=document-using-sheet-with-min-width-1000px/iframe

There are also various user actions that can similarly change the width 
of even the toplevel window in CSS pixels such that it's larger than the 
nominal device width in CSS px (e.g. zooming out, in UAs that change the 
size of CSS px when you zoom).



It merely re-evaluates if an inapplicable
query would apply if it were a device query instead of a viewport
query, and if not, the stylesheet is not loaded at all.


Except device queries and viewport queries are not at all the same 
thing, of course.  Conflating the two may be ok for a library that 
developers are free to not use if it's making assumptions that are not 
true in their use cases, but it's really not OK for a UA to do.


I agree that better UA behavior here would be nice, but it's not trivial 
to do without breaking sites or creating a poor user experience.



2. Reducing the amount of time that an unresponsive stylesheet can
block page rendering


Yes, indeed.

-Boris


Re: [whatwg] Proposal for change in recommendation for loading behavior of non-applicable stylesheets

2012-06-10 Thread Scott Jehl
Thanks for responding, Boris!

 One issue with this is that in many cases the UA may not yet know what
 media queries apply to the document when starting the sheet loads.  In
 some cases it does, of course, but those may be rarer than you think…

That makes sense. For my own understanding, do you have any examples of media 
queries that can't be determined until a later time?

In observing trends in web development and in my own work, it seems to me that 
the following types of queries are most commonly used to deliver cross-device 
Responsive designs:

min-width
max-width
min-device-width
max-device-width
min-device-pixel-ratio

I'd presume a UA would be able to run these before a page has begun loading, or 
at least after a meta[name=viewport] element has loaded (so that would need to 
come before stylesheets in the head to take advantage of this feature).

 Is that not the case?


I'm not entirely sure I understand your iframe example and how it would relate 
to the media query differently than any viewport width. I'd love a 
clarification on that part, but the following part is clear to me:

 There are also various user actions that can similarly change the width of 
 even the toplevel window in CSS pixels such that it's larger than the nominal 
 device width in CSS px (e.g. zooming out, in UAs that change the size of CSS 
 px when you zoom).


Okay. But even if a user's preferences have previously changed the default 
font-size of the browser (say, by increasing their font size), wouldn't the UA 
would be privy to that size at load time, and be able to use that in 
determining whether, say, an EM-based media query was applicable to the 
viewport width or not?


 Except device queries and viewport queries are not at all the same thing, of 
 course.  Conflating the two may be ok for a library that developers are free 
 to not use if it's making assumptions that are not true in their use cases, 
 but it's really not OK for a UA to do.


Understood. This example would be difficult to apply broadly, which is 
unfortunate as it'd be the area where the actual savings in HTTP requests could 
be made.

That said, merely deferring the load of stylesheets that don't apply at initial 
load would be a huge performance improvement for users. 

In a few large-scale responsive designs I've reviewed, sometimes more than half 
of the CSS delivered in the head of a page does not apply at all in 
small-screen contexts, yet the device must wait while all of it loads.


 2. Reducing the amount of time that an unresponsive stylesheet can
 block page rendering
 
 Yes, indeed.


Excellent. I'd suggest something in the 6-8 seconds range would be reasonable 
(and that's the timeout implemented in my sample framework above), but that may 
be too aggressive for most folks' tastes.

Thanks again!

Scott



Re: [whatwg] Proposal for change in recommendation for loading behavior of non-applicable stylesheets

2012-06-10 Thread Boris Zbarsky

On 6/10/12 4:33 PM, Scott Jehl wrote:

One issue with this is that in many cases the UA may not yet know what
media queries apply to the document when starting the sheet loads.  In
some cases it does, of course, but those may be rarer than you think…


That makes sense. For my own understanding, do you have any examples of media 
queries that can't be determined until a later time?


Well, for example inside an iframe determining whether a width query 
matches requires flushing out DOM construction, style computation, and 
layout on the parent document.  Right now none of that is done, at least 
in Gecko, when kicking off a stylesheet load.


And note that this would be racy: the iframe width might depend on other 
things in the parent document that haven't loaded yet (e.g., think a 
grid layout where the sizes of the grid cells depend on images whose 
intrinsic size is not known yet).


Even for a non-iframe document in Gecko right now the style loads can 
start before any sort of presentation has been set up and before the 
document knows what screen it's on, which viewport it's being rendered 
into, etc.  Communicating this information to the style loader is 
obviously possible, but would involve flushing out various work that's 
done lazily and reduces parallelism opportunities



I'd presume a UA would be able to run these before a page has begun loading, or 
at least after a meta[name=viewport] element has loaded (so that would need to 
come before stylesheets in the head to take advantage of this feature).

  Is that not the case?


I don't think we can rely on it being the case, necessarily 
especially long-term (e.g. the addition of meta viewport changed how 
all this stuff works, and I bet there will be future spec changes that 
change it too).



I'm not entirely sure I understand your iframe example and how it would relate 
to the media query differently than any viewport width.


See above about having to do extra work, not normally needed, to lay out 
the parent document and the inherent races that entails.



Okay. But even if a user's preferences have previously changed the default 
font-size of the browser (say, by increasing their font size), wouldn't the UA 
would be privy to that size at load time, and be able to use that in 
determining whether, say, an EM-based media query was applicable to the 
viewport width or not?


The point is that if the sheet is not loaded at all and then the user 
zooms the page so that the viewport size changes while the page is 
loaded... what happens? Recall that this part of the proposal was to not 
load the sheet at all, as opposed to lazy-loading it.  Lazy-loading is 
definitely desirable, though I'd be wary of the specs requiring it, 
especially because such requirements are not easily testable.  E.g. 
nothing in the spec actually has any requirements at all on starting 
rendering.


I'm not sure what the sanest thing is to do here in spec terms.  :(

-Boris