Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-values] Define crossorigin, preload and async URL modifiers #1603

Open
AmeliaBR opened this issue Jul 13, 2017 · 22 comments
Open

[css-values] Define crossorigin, preload and async URL modifiers #1603

AmeliaBR opened this issue Jul 13, 2017 · 22 comments
Assignees
Labels
css-values-5 topic: urls Tracking issues that'll need edits when CSS URLs are defined on top of Fetch.

Comments

@AmeliaBR
Copy link
Contributor

The HTML img element (and also preload links and other references to external files) take a crossorigin attribute. It's purpose is to upgrade a request for an asset that normally doesn't need CORS permissions, so that the same asset can later be re-used in a context that does need CORS permissions.

CSS does not currently have this option. URLs in some properties (filters, clipping paths, masks that reference <mask> elements, and shape-outside images) require crossorigin="anonymous" mode. But URLs in older properties (background-image, border-image) don't request CORS permissions.

This causes caching headaches if you use the same asset file in multiple properties: even if the server is set up to use the correct caching headers, the same file would be download twice (once with CORS headers, and once without). If the server is not set up correctly, the CORS-request often fails because the cached version of the file does not have the correct headers.

Some examples of cases where you'd want the same asset file with different CORS requirements:

  • A background-image that is also used as a shape-outside image for the same element
  • An SVG file that is used as an image (e.g., background image, border image), but also includes <mask>, <filter>, or <clipPath> effects for enhancing the final presentation of the element.
  • Any CSS image that will also be used in a canvas animation (e.g., a logo image that gets turned into a fancy animated loader graphic)

Currently, the only solution is to add a preload link to the markup to force the browser to fetch the assets with CORS permissions before the CSS can trigger its own fetch.

Related issues:

But I couldn't find an issue or proposal specifically about allowing CORS upgrades to CSS asset fetches.

The is, in my opinion, a logical use of the url-modifier token that CSS Values 3 introduced into the url() function:

The url() function supports specifying additional s, which change the meaning or the interpretation of the URL somehow. A is either an or a functional notation.

This specification does not define any s, but other specs may do so.

I don't have opinions on syntax beyond that, except that the keywords should match the ones used in HTML.

@AmeliaBR
Copy link
Contributor Author

Related: #2994 on preload modifier and #2095 on async modifier. We should probably address them all at the same time to get consistent syntax and implementation guidelines.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed URL modifiers for image loading, and agreed to the following:

  • RESOLVED: Unknown <url-modifier>s get silently ignored (rather than invalidating the function).
The full IRC log of that discussion <presenter_> Topic: URL modifiers for image loading
<astearns> github: https://github.com//issues/1603
<presenter_> ScribeNick: presenter_
<presenter_> AmeliaBR: So there are several modifiers that exist in HTML image loading.
<presenter_> #1603 is crossorigin.
<presenter_> AmeliaBR: background-images don't need crossorigin info, so if it's the first thing it sees, browser fetches it without crossorigin.
<presenter_> AmeliaBR: If you then use it for something else that *does* care about CORS, browser has to fetch a second time.
<presenter_> AmeliaBR: Or it just gets reused and errors.
<presenter_> AmeliaBR: Both are suboptimal.
<presenter_> AmeliaBR: Can get around it today by adding a <link rel=preload>, but then need to alter markup to adjust CSS.
<presenter_> AmeliaBR: So having a way to indicate in CSS that something should be requested with crossorigin permissions for later would be useful.
<fantasai> tantek: I agree completely with the use case and with the more gneral use case, that eveyrthing you can tweak about image loading in HTML shoudl be tweakable from CSS as well
<fremy> ScribeNick: presenter_
<fantasai> hober: I agree that CSS and HTML should match here.
<fantasai> hober: But both should be sitting on top of Fetch. Fetch should hav esome keywords, and we use those keywords
<presenter_> hober: I agree that CSS should match here, but both should be in Fetch and these should be based on this.
<presenter_> AmeliaBR: good point
<presenter_> AmeliaBR: I think all of these should be addressed together with a common syntax.
<hober> s/CSS should match/CSS should match HTML/
<presenter_> AmeliaBR: I don't know what's the nicest or more author-friendly syntax, but good to consider them all together, not piecewise.
<astearns> https://github.com//issues/2994
<astearns> https://github.com//issues/2095
<astearns> https://github.com//issues/3659
<presenter_> AmeliaBR: Other ones open are #2994 on preloading something, #2095 for async decoding, and #3650 for lazy loading
<presenter_> AmeliaBR: issues for async and lazyload is that browser defaults for CSS images are different from HTML content images.
<xfq> s/#3650/#3659/
<presenter_> AmeliaBR: Maybe can't copy html, need to think about what makes sense for CSS specifically
<presenter_> jensimmons: Yes, we need this. Proposal is to put the burden on authors to set this up correctly?
<presenter_> jensimmons: Authors already have a hard time on CORS compat.
<presenter_> jensimmons: Can we put the burden on the browser instead?
<presenter_> TabAtkins: I suspect not. These are all behavior changes, so changing defaults could break changes.
<presenter_> AmeliaBR: Also if browser has to consider all possible cases for how it'll request an image before it can send the request, it can get messy/slow, especially with dynamic loading
<presenter_> astearns: Yeah, browser might not know that a *future* load will need CORS, so there's no way for it to tell without a hint.
<presenter_> astearns: So on the align-with-fetch issue, does Fetch have keywords for all these topics we can follow?
<presenter_> emilio: Firefox already does async decoding on all images.
<presenter_> myles_: Really? We did that but had to roll it out.
<presenter_> emilio: We do it unless it's something our image library can tell is fast.
<presenter_> TabAtkins: Is ther an attribute for async decoding on <img>? Not sure we should do anything img doesn't.
<bkardell_> proposed* I think
<presenter_> AmeliaBR: Yeah, there's a `decoding="auto|sync|async"` attribute proposal.
<chris> :)
<presenter_> emilio: What's the story with unknown url modifiers? Would be sad if you have to rewrite the url several times for different combos of browser support.
<presenter_> TabAtkins: Not defined right now. We should decide how we want to do error handling
<presenter_> myles_: We solved this for src() with forgiving handling, split on top-level commas and ignore unknown stuff.
<presenter_> astearns: Yeah, good to match.
<AmeliaBR> URL modifiers https://drafts.csswg.org/CSS-values/#url-modifiers
<presenter_> AmeliaBR: Reading the definition of url-modifier, it looks like they can't be used on unquoted urls or just-string urls. That means it needs to have a quoted string inside?
<presenter_> TabAtkins: Yes.
<presenter_> fremy: Edge currently ships with the quoted-url-as-function-token behavior.
<presenter_> emilio: Also Firefox.
<presenter_> astearns: So any objection to silently ignore unknown url-modifiers?
<presenter_> RESOLVED: Unknown <url-modifier>s get silently ignored (rather than invalidating the function).
<presenter_> AmeliaBR: So I think the rest of the issue is, align CSS's image loading support with HTML's support, via url modifiers.
<presenter_> TabAtkins: Agreed.
<presenter_> <br>

@svgeesus
Copy link
Contributor

svgeesus commented May 8, 2019

cross-origin, preload and async would certainly be useful for downloaded webfonts, color profiles, etc as well as images. So doing this via <url-modifiers> is the correct approach and would help with these issues as well:

#3659
#450
#3069
#297

@svgeesus svgeesus changed the title [css-values] Define a crossorigin URL modifier [css-values] Define crossorigin, preload and async URL modifiers May 8, 2019
@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed Define crossorigin, preload and async URL modifiers.

The full IRC log of that discussion <dael> Topic: Define crossorigin, preload and async URL modifiers
<dael> github: https://github.com//issues/1603
<dael> AmeliaBR: I didn't put this on the agenda, chris did. Is he on?
<dael> Rossen_: I don't see regrets, but he might still be on vacation
<dael> AmeliaBR: We talked about this at last F2F. We resolved some syntactic details about URL functions with modifiers. General consensus we should pursue harmonizing with HTML for image loading modifiers. Waiting on someone to sit down and write a proposal. I haven't done that. Not sure what Chris wanted to do on call
<dael> Rossen_: If we need to wait that's fine. I'll remove agenda+ so that it doesn't come back until it's ready.

@Malvoz
Copy link
Contributor

Malvoz commented Jan 27, 2020

Also consider integrity for SRI, see w3c/webappsec-subresource-integrity#40 and w3c/webappsec#306.

@astearns
Copy link
Member

I was just reminded of this proposal when one of our engineers ran into a problem where they need to request background-image URLs in CORS mode. @tabatkins, @fantasai, or @AmeliaBR (or anyone, really) could we get some draft text for this?

@rhythmone
Copy link

Is this issue stuck? AWS just confirmed this as a blocker in Amplify for both React and Vue... thus rendering these CSS features useless. What is the next step? What kind of support is needed to get this across the finish line?

@tabatkins
Copy link
Member

I'm poking around at @import right now to get it defined on top of Fetch. Once I figure out all those details, I should be able to transfer the knowledge over to general url() usage, such that these parameters can be usefully defined.

@fantasai fantasai added css-values-5 topic: urls Tracking issues that'll need edits when CSS URLs are defined on top of Fetch. and removed css-values-4 Current Work labels Sep 23, 2021
@noamr
Copy link
Collaborator

noamr commented Jul 31, 2022

I'm poking around at @import right now to get it defined on top of Fetch. Once I figure out all those details, I should be able to transfer the knowledge over to general url() usage, such that these parameters can be usefully defined.

I guess this is done now? :)

@noamr
Copy link
Collaborator

noamr commented Dec 13, 2022

I think this is important. I'd be to make an initial PR.
I believe we should be careful with preload - not sure if we want to make it so that CSS actively loads anything but imported stylesheets, when the DOM might not even have that image. The problem of unused preload is pretty common on the web, and this might make it worse.

Perhaps we can start with standard loading modifiers (crossorigin and integrity) and expand it to async and perhaps preload later?

Based on url-modifier, suggesting it would look like:
background-image: url('...' crossorigin(anonymous) integrity(sha1-blabla01234) referrerpolicy(same-origin))`

@tabatkins
Copy link
Member

Lol this slipped thru my fingers.

I guess this is done now? :)

Well, you did it, so I didn't exactly gain the knowledge to transfer over to here. ^_^

Perhaps we can start with standard loading modifiers (crossorigin and integrity) and expand it to async and perhaps preload later?

Sounds reasonable.

Based on url-modifier, suggesting it would look like:

Yes, tho the integrity hash needs to be a string, not an ident. It comes from outside CSS so there's no guarantee it'll always stick to our ident syntax rules. The other two are good tho - technically those values don't come from CSS either, but they're a finite set so we can always give a different "CSS-compatible" keyword if necessary (tho that seems incredibly unlikely).

@noamr
Copy link
Collaborator

noamr commented Dec 14, 2022

Lol this slipped thru my fingers.

I guess this is done now? :)

Well, you did it, so I didn't exactly gain the knowledge to transfer over to here. ^_^

Perhaps we can start with standard loading modifiers (crossorigin and integrity) and expand it to async and perhaps preload later?

Sounds reasonable.

Based on url-modifier, suggesting it would look like:

Yes, tho the integrity hash needs to be a string, not an ident. It comes from outside CSS so there's no guarantee it'll always stick to our ident syntax rules. The other two are good tho - technically those values don't come from CSS either, but they're a finite set so we can always give a different "CSS-compatible" keyword if necessary (tho that seems incredibly unlikely).

Sounds good! I started a PR: #8222
I can probably use some (a lot of) editorial help there but I've set the functional foundations.

@tabatkins
Copy link
Member

#8222 is now merged, which allows setting the some CORS/referer settings, and an integrity hash. Handling async and preload is still TODO, but it looks great so far!

@cdoublev
Copy link
Collaborator

4.5.3. URL Modifiers

[...] This specification does not define any <url-modifier>s, but other specs may do so. [...]

4.5.5. Request URL Modifiers

The <request-url-modifier>s represent <url-modifier>s that affect the resource’s request. [...]

Do you plan to edit 4.5.3 after handling async/preload or is it an oversight?

@noamr
Copy link
Collaborator

noamr commented Mar 13, 2023

4.5.3. URL Modifiers
[...] This specification does not define any <url-modifier>s, but other specs may do so. [...]
4.5.5. Request URL Modifiers
The <request-url-modifier>s represent <url-modifier>s that affect the resource’s request. [...]

Do you plan to edit 4.5.3 after handling async/preload or is it an oversight?

Oversight!

@tabatkins
Copy link
Member

Agenda+ since we didn't actually get a resolution for adding these, hopefully this should just be a rubber-stamp on the existing work.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-values] Define crossorigin, preload and async URL modifiers, and agreed to the following:

  • RESOLVED: Leave the values in Level 5
The full IRC log of that discussion <emeyer> github: https://github.com//issues/1603
<emeyer> TabAtkins: We agreed to add additional URL modifiers
<emeyer> …ALl the things you can do with Fetch or with HTML links
<emeyer> …We never defined them, put them off to another level
<emeyer> …Gnome went ahead and defined three of them [missed the three]
<emilio> q+
<emeyer> …THe mechanics are reasonable and match up with what you’d do in HTML
<astearns> s/Gnome/Noam/
<emeyer> …Does anyone have any objections to these, and are they fine for Values 4 or do they need to wait for Values 5?
<astearns> ack emilio
<emeyer> emilio: What do preload and async do?
<emeyer> …Preloading in the context of CSS values doesn’t make a lot of sense ot me
<emeyer> TabAtkins: Noam added crossorigin, integrity, and referrer
<emeyer> s/ot/to/
<TabAtkins> https://w3c.github.io/csswg-drafts/css-values-5/#request-url-modifiers
<emeyer> emilio: I’m curious about the integrity string, is that a function?
<emeyer> TabAtkins: Yep, takes a string that is the hash
<emeyer> emilio: Seems fine to me
<astearns> ack fantasai
<emeyer> fantasai: I’d prefer to leave them in Level 5 because they’re already drafted there
<emeyer> …I’d also like to get L4 to CR by closing out issues
<emeyer> astearns: Anyone want to argue for L4?
<emilio> q+
<emeyer> TabAtkins: L4 holds some things that aren’t implemented, so we should kick those out; these are stable and appropriate
<emeyer> …I don]t want to kick these out for arbitrary reasons
<astearns> ack emilio
<emeyer> emilio: I just realized we force crossorigin to be anonymous for CSS already
<emeyer> …We need to define whether you can override it; I don’t think you should be able to
<tantek> +1 to consistent methodology for level 4 vs 5, ok with dropping things from L4 that have zero implementations. probably a good move before CR
<emeyer> …Masks, for example, require anonymous crossorigin loads
<emeyer> …So we should define that
<emeyer> TabAtkins: I don’t think they’re defined in a way that hooks into these, so we need to review that
<emeyer> astearns: We should resolve to leave these in L5; any objections?
<emeyer> RESOLVED: Leave the values in Level 5

@LeaVerou
Copy link
Member

LeaVerou commented Aug 1, 2024

What’s the status of this? Is it waiting for implementations or is there spec work remaining?

async is pretty essential. It's the reason libraries like Font Awesome have to resort to <script> for their embed code.
Tons of questions online about CSS async loading, all resorting to JS in one way or another, with the prevailing solution being this:

<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">

@noamr
Copy link
Collaborator

noamr commented Aug 1, 2024

async is a bit

What’s the status of this? Is it waiting for implementations or is there spec work remaining?

async is pretty essential. It's the reason libraries like Font Awesome have to resort to <script> for their embed code. Tons of questions online about CSS async loading, all resorting to JS in one way or another, with the prevailing solution being this:

<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">

This is a separate issue. Async here is for async image decoding and was split into #2095.
I believe you meant to comment on whatwg/html#3983?

@LeaVerou
Copy link
Member

LeaVerou commented Aug 1, 2024

@noamr it's also a CSS WG issue, as it affects @import. If this was solved in @import, it would already provide a better solution than the current status. But thanks for sharing the WHATWG issue! I'll comment there too.

@cdoublev
Copy link
Collaborator

Unknown <url-modifier>s get silently ignored (rather than invalidating the function)

I guess url("img.jpg" crossorigin(unknown)) should still be valid then, right?

@noamr
Copy link
Collaborator

noamr commented Sep 10, 2024

Unknown <url-modifier>s get silently ignored (rather than invalidating the function)

I guess url("img.jpg" crossorigin(unknown)) should still be valid then, right?

Yea, in case some other browser respects it somehow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-values-5 topic: urls Tracking issues that'll need edits when CSS URLs are defined on top of Fetch.
Projects
None yet
Development

No branches or pull requests