w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 661 forks source link

[css-cascade] Provide an attribute for assigning a <link> to a cascade layer #5853

Open mirisuzanne opened 3 years ago

mirisuzanne commented 3 years ago

This was raised on #4969, related to the Cascade level 5 spec.

We've defined a syntax for cascade layers to be declared as code-blocks or url imports:

@layer reset url(remedy.css); 

@layer reset {
  audio[controls] { display: block; }
}

If we're allowing authors to import entire stylesheets into a layer, it seems appropriate to make that available on <link> and <style> tags as well. For performance reasons, those are more likely to be used - rather than chaining imports. I'm proposing a layer attribute:

<link rel="stylesheet" href="remedy.css" layer="reset">

<style layer="reset">
  audio[controls] { display: block; }
</style>
frivoal commented 3 years ago

I suspect that's not going to work, as existing user agents would just ignore the layer attribute, and assign all those styles to the default layer instead, so that's not going to be forward compatible.

For <style>, I'm not so sure it's critical: if we can find a nice syntax that's forward compatible, then great, but otherwise, it's just syntactic sugar: if you can do

<style layer="reset">
  audio[controls] { display: block; }
</style>

you can also do

<style>
@layer reset {
  audio[controls] { display: block; }
}
</style>

For <link> it's more useful though, as you may be trying to load into a particular layer a stylesheet that you cannot modify.

css-meeting-bot commented 3 years ago

The CSS Working Group just discussed Providing an attribute for providing a link to a cascade layer.

The full IRC log of that discussion <myles> Topic: Providing an attribute for providing a link to a cascade layer
<astearns> github: https://github.com/w3c/csswg-drafts/issues/5853
<myles> miriam: This might need to to HTML.
<argyle> https://www.irccloud.com/pastebin/zWOYuXvD/
<argyle> oh! full snippets!?
<myles> miriam: The idea is if we're able to import into a layer in a stylesheet, shoudl be able to do this from a link to a stylesheet? Like an attribute. But there are issues. Attributes are usually ignored if the browser doesn't support them. Then you'd get a different fallback behavior than if the browser ignored a layer block
<myles> florian: I dont' think that syntax can work. Doing it from HTML seems valid. but it probably couldn't be <missed> it would have to be something else because of fallback .Maybe rel="layer"
<myles> florian: other than that, sure, why not
<myles> fremy: there's an attribute for media
<myles> fremy: we can maybe use it in have a special syntax: media="layer=..."
<myles> fremy: I dunno,t hat was a random thought. IN browsers which don't support layer, it would never match because this media doesn't exist
<myles> astearns: I'm not a fan of nesting it in media=
<myles> florian: It would be ugly but it would work.
<myles> astearns: For my clarification: florian, the layer attribute would not work, but just not in a link element, or also not in a style element
<myles> florian: if you have <link> that loads a stylesheet that's ordinary in every respect except it also has a layer attribute, it wouldn't work because browsers would do a normal import, which isn't compatible behavior.
<myles> astearns: So it would also be a problem in <style>
<myles> miriam: The <style> doesn't need this because you can just put a layer inside of it easily.
<myles> fantasai: We should table this until we have a specific proposal
<myles> florian: Or push to WHATWG
<bkardell_> you could <style>@import ... right?
<myles> TabAtkins: let's open an issue on WHATWG.
<tantek> sounds reasonable
<myles> TabAtkins: Mabye we can stash it in media= like fremy said. They can think about it in WHATWG
<myles> astearns: ok.
<fantasai> +1 bkardell_, this might not be worth solving in HTML
valtlai commented 3 years ago

I would suggest <style type="layer(reset)"> (similar to <script type="module">).

tabatkins commented 3 years ago

The problem with that is that <script type> actually has an effect (if unrecognized, it won't run the script), while <style type> does not (the attribute is simply ignored).

domenic commented 3 years ago

Might it be time to finally implement <style src=""> and bring balance to the Forceweb platform surface syntax for including external resources???

mirisuzanne commented 3 years ago

Without this, the only way to import 3rd-party styles from a CDN into a layer would be @import, which is generally considered a performance issue. I know that's especially true when the import is in an external CSS file, causing a chain of requests. Is that still an issue when the imports are inline? Do these have different performance implications?

<link rel="stylesheet" href="https://example.com/framework.css">

<style>
  @import url('https://example.com/framework.css');
</style>

If so, we might want to revisit the priority of this? It seems like a fairly common use-case.

xiaochengh commented 3 years ago

@mirisuzanne These two should have the same performance (at least in Chromium). Both are captured by preload scanners.

yoavweiss commented 3 years ago

I think this is a problem worth solving, either by hacking a supports syntax into media (which can be useful in other contexts as well - /cc @jridgewell) or by going the <style src> route that @domenic suggested.

@mirisuzanne These two should have the same performance (at least in Chromium). Both are captured by preload scanners.

The Chromium/WebKit preload scanner for CSS imports is significantly more fragile than its HTML equivalent, as it doesn't perform "real" tokenization. It'd be better to not put the weight of this feature's performance on it. Also, Firefox doesn't have such a preload scanner AFAIK.

mirisuzanne commented 2 years ago

What is the next step for pushing a <style src> proposal forward? How much of that can we do here in the CSSWG?

tabatkins commented 2 years ago

Little, I suspect. Next would be socializing it in WHATWG with an issue, getting some impl buy-in, and then writing a PR.

mirisuzanne commented 2 years ago

2a2200e defines the production necessary for HTML to reference media & supports conditions as a single syntax. I think otherwise we can close this, and continue the conversation/progress in the linked WHATWG issue, and the HTML spec.

mirisuzanne commented 2 years ago

I'm working on a PR against the HTML spec to allow support queries in <link media> (https://github.com/whatwg/html/pull/7658) but noticed the product of the media attribute seems to rely on a definion of CSSOM media & MediaList likely generated from text.

That is to say, I think we might need to update CSSOM in order to make this possible? Would be glad for thoughts/advice (@tabatkins or @emilio, maybe?) on the best way to approach this.

digitaldonkey commented 2 years ago

@frivoal what you mean with forward compatible?

Having a link with @layer is a really important for most CMSs systems. Solving this (in any flavor) would boots feature adoption. Please go on that we get this into the world.

MSanbira commented 2 years ago

@frivoal to your statement, there are npm addons like Material-UI that inject <style> tags dynamically and so to manipulate their content every time is a bit annoying and hacky. I do this in our main React app, and it works, but I would like the option to set a simple attribute instead of editing the full content inside the <style>.

another thing is when I go over all the style tags every <head> change and try to set their layer I need first to check that the CSS is not already in a layer, and checking an attribute will be a lot easier.

like @digitaldonkey said more options to set CSS chunks to layers will boost feature adoption. real and messy existing apps need more tools in their arsenal for unique problems.

mirisuzanne commented 2 years ago

Florian's comment was not that we shouldn't do this, but that an attribute alone will cause compatibility issues - which is true. Any browser that doesn't understand the new layer attribute (on a link or a style element) will load those styles un-layered. That's an issue we need to address. And it's true that it is more of a problem for link (which doesn't have a manual alternative), and that it would be ideal to solve for both link and style.

This is something that we are actively working on for both link and style elements in the WHATWG proposal linked above. At this point it has to be solved in HTML, not in CSS. I don't think anyone still needs convincing that this is something we should do, the questions remaining are all about how exactly we do it -- and those conversations are happening in the WHATWG.

shayded-exe commented 1 year ago

Florian's comment was not that we shouldn't do this, but that an attribute alone will cause compatibility issues - which is true. Any browser that doesn't understand the new layer attribute (on a link or a style element) will load those styles un-layered. That's an issue we need to address. And it's true that it is more of a problem for link (which doesn't have a manual alternative), and that it would be ideal to solve for both link and style.

Is this really such a problem though? The only people would would run into this problem, are the ones who choose to use the feature. In my case we only need to support chrome, so at least for us this is a non-issue, but I suspect that it wouldn't be an issue for many other people who would only benefit from having the feature available even with the gotcha. It would ease a lot of pain for us dealing with third party CSS in an environment where we have limited control.

I understand it is a problem that does need to be solved, but I don't see a reason it should completely hold up this feature. Please let me know if there's something I'm missing and thank you for the work y'all do. I know there's a lot of complex politics involved and whatnot.

o-t-w commented 1 week ago

This problem was raised 5 years ago. If it had been specced and implemented at the time then we'd be able to use it now, instead worrying about backwards compatibility is causing a delay... Obviously developers could just wait until this feature has broad support before using it...