RESOLVED FIXED 39455
<link> elements with media queries that do not affect the current page can be delayed
https://bugs.webkit.org/show_bug.cgi?id=39455
Summary <link> elements with media queries that do not affect the current page can be...
Joseph Pecoraro
Reported 2010-05-20 16:24:07 PDT
Created attachment 56644 [details] [IMAGE] Web Inspector Shows Waiting for a useless media="print" resource HTML5 describes the <link> element's media attribute here: http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#attr-link-media > However, if the link is an external resource link, then the media attribute > is prescriptive. The user agent must apply the external resource when the > media attribute's value matches the environment and the other relevant > conditions apply, and must not apply it otherwise. If the browser is unaffected by the media queries in the <link media="..."> then it is safe to assume that the content is not immediately necessary and time could be better spent download other resources. Also, it may not be necessary to prevent the DOMContentReady or onload event's for the resource. In the attached image, the "print.css" file is a link with media="print". These styles do not affect the document, yet it was downloaded and delayed some events from firing.
Attachments
[IMAGE] Web Inspector Shows Waiting for a useless media="print" resource (145.63 KB, image/png)
2010-05-20 16:24 PDT, Joseph Pecoraro
no flags
Timothy Hatcher
Comment 1 2010-05-20 16:27:14 PDT
This also happens for type="alternate stylesheet".
Alexey Proskuryakov
Comment 2 2010-05-20 16:57:04 PDT
Firing load events before alternate stylesheets have loaded can easily have compatibility consequences - a script running from onload may want to switch stylesheets, for example. Even media="print" stylesheets are exposed via CSSOM. Loading them after other resources sounds like a great idea to me.
Alexey Proskuryakov
Comment 3 2011-01-31 21:59:00 PST
Antti, is this fixed now?
Karl Dubost
Comment 4 2022-08-30 18:37:57 PDT
Antti, Alexei, Should we close this one in favor of Bug 243424
Ahmad Saleem
Comment 5 2022-11-09 17:30:46 PST
*** Bug 243424 has been marked as a duplicate of this bug. ***
Radar WebKit Bug Importer
Comment 6 2022-11-09 22:50:20 PST
Vadim Makeev
Comment 7 2022-11-27 14:35:50 PST
I’d like to move my initial comment from the bug, closed as duplicate, so it won’t be lost. Imagine a simple situation, two CSS files linked in the head: <link rel="stylesheet" href="screen.css"> <link rel="stylesheet" href="print.css" media="print"> Currently, WebKit will wait for both of them to be loaded before rendering anything at all. It makes sense since CSS is a render-blocking resource. But the browser won’t use print.css for rendering because the implicit “screen” media type doesn’t match the “print” value. And it’s clear from the HTML parsing stage: this resource is not render-blocking. Both Firefox and Chromium will keep loading print.css with lower priority and will start rendering once screen.css is available. It won’t save traffic but will make the page appear faster. The same could be used not only for printing but for many different applications, that would make CSS performance better: 1. Color scheme: dark.css should not block rendering if the current scheme is light <link rel="stylesheet" href="light.css" media="(prefers-color-scheme: light)"> <link rel="stylesheet" href="dark.css" media="(prefers-color-scheme: dark)"> 2. It could be possible to split CSS into separate files based on breakpoints <link rel="stylesheet" href="base.css"> <link rel="stylesheet" href="mobile.css" media="(max-width: 767px)"> <link rel="stylesheet" href="tablet.css" media="(min-width: 768px) and (max-width: 1023px)"> <link rel="stylesheet" href="desktop.css" media="(min-width: 1024px)"> 3. It could be possible to offload some enhancements based on device properties or user preferences: <link rel="stylesheet" href="retina.css" media="(min-resolution: 2dppx)"> <link rel="stylesheet" href="heavy.css" media="(prefers-reduced-data: no-preference)"> <link rel="stylesheet" href="animation.css" media="(prefers-reduced-motion: no-preference)"> Well, it’s currently possible, but not in WebKit. Here’s the demo with breakpoints: https://pepelsbey.dev/articles/conditionally-adaptive/demo/index.html And the article, exploring the idea to use this behavior: https://pepelsbey.dev/articles/conditionally-adaptive/
Vadim Makeev
Comment 8 2022-11-27 14:37:55 PST
Here’s another reason for this behavior to be aligned with the rest of the browsers. There’s a popular technique of CSS lazy loading introduced in Filament Group blog in 2019 https://www.filamentgroup.com/lab/load-css-simpler/ <link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'"> I see it used and mentioned here and there as one of the best and simplest option. The article states: > …the browser will load the stylesheet without delaying page rendering, asynchronously Which is not the case for Safari: it will be Render-blocking. No one seems to expect such incompatible behavior.
Alexey Proskuryakov
Comment 9 2022-12-04 18:08:41 PST
*** Bug 248724 has been marked as a duplicate of this bug. ***
Vadim Makeev
Comment 10 2023-02-06 04:23:41 PST
There’s another use case for this behavior that might affect performance on some websites. This quite popular CSS lazy-loading trick doesn’t work in Safari: <link rel="stylesheet" href="critical.css" > <link rel="stylesheet" href="deferred.css" media="print" onload="this.media='all'" > <noscript> <link rel="stylesheet" href="deferred.css" > </noscript> All other browsers will render styles from critical.css and keep loading deferred.css in the background to apply them once they’re loaded. But Safari will wait for deferred.css and not render anything until it’s loaded. See more details in my the post https://pepelsbey.dev/articles/lazy-loading-safari/
Antti Koivisto
Comment 11 2023-02-07 03:42:29 PST
Antti Koivisto
Comment 12 2023-02-07 03:47:31 PST
The issue is the we allow stylesheets with non-matching media delay the visually non-empty milestone. This only comes into play if the page is simple enough that it doesn't hit the milestone by having enough visual content to reach the threshold.
Vadim Makeev
Comment 13 2023-02-07 06:05:41 PST
Nice! Does it affect CSS files loaded via @import? There’s a similar issue in Chromium https://bugs.chromium.org/p/chromium/issues/detail?id=1001078 These two should work the same: <link rel="stylesheet" href="/style.css" media="(prefers-color-scheme: light)"> <style> @import url(import.css) (prefers-color-scheme: light) </style>
Antti Koivisto
Comment 14 2023-02-07 06:28:33 PST
(In reply to Vadim Makeev from comment #13) > Nice! Does it affect CSS files loaded via @import? There’s a similar issue > in Chromium https://bugs.chromium.org/p/chromium/issues/detail?id=1001078 > > These two should work the same: > > <link rel="stylesheet" href="/style.css" media="(prefers-color-scheme: > light)"> > > <style> > @import url(import.css) (prefers-color-scheme: light) > </style> No, worth a separate bug.
Anthony Ricaud
Comment 15 2023-02-07 06:30:49 PST
@Antti: The way I read your comment, it seems this bug only affects testcase-like pages. So not many real world pages should be affected. Am I understanding correctly? If that's the case, @Vadim, you may want to update your post to reflect that ?
Vadim Makeev
Comment 16 2023-02-07 06:40:59 PST
> The way I read your comment, it seems this bug > only affects testcase-like pages. So not many > real world pages should be affected @Anthony Ricaud: There are at least two real-world use cases that I mentioned earlier in this issue. 1. Print styles that block rendering, although they’re not used 2. Lazy-loading technique that relies on the non-blocking behavior Both of them are not test case-like. > You may want to update your post to reflect that? I already updated the post to mention the PR with the fix. Otherwise, I think it’s still correct.
Sam Sneddon [:gsnedders]
Comment 17 2023-02-07 07:58:43 PST
(In reply to Vadim Makeev from comment #16) > > The way I read your comment, it seems this bug > > only affects testcase-like pages. So not many > > real world pages should be affected > > @Anthony Ricaud: There are at least two real-world use cases that I > mentioned earlier in this issue. > > 1. Print styles that block rendering, although they’re not used > 2. Lazy-loading technique that relies on the non-blocking behavior > > Both of them are not test case-like. However, very few pages on the web are HTML files with an empty body element: _that_ is what is being called test case-like. Add a paragraph or two to the body, and behaviour should change, and you'll see the body straight away.
Vadim Makeev
Comment 18 2023-02-07 08:18:37 PST
Oh, I see now, you’re right. I calculated that it takes a bit more than 200 characters to change the behavior. But with a typical modern SPAs setup, where you have empty <body> and a bunch of scripts, it might not be enough to trigger the proper behavior: <body> <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> <script src="app.js"></script> </body> This kind of page won’t get CSS loading benefits.
EWS
Comment 19 2023-02-07 09:34:06 PST
Committed 259963@main (9e31d4e46121): <https://commits.webkit.org/259963@main> Reviewed commits have been landed. Closing PR #9746 and removing active labels.
Vadim Makeev
Comment 20 2023-02-08 01:00:45 PST
@Sam Sneddon: I updated the article, thank you! https://pepelsbey.dev/articles/lazy-loading-safari/#full-body
Note You need to log in before you can comment on or make changes to this bug.