Re: [whatwg] Proposal for change in recommendation for loading behavior of non-applicable stylesheets
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
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
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
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
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
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
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
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
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
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