-
Notifications
You must be signed in to change notification settings - Fork 659
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-cascade-5] Allow authors to explicitly place unlayered styles in the cascade layer order #6323
Comments
Definitely welcome to have that level of control. If you didn't want a reserved name you could use different @ name. e.g. |
Idk if it's a good idea, but one possibility would be to just leave out the identifier.
|
Thinking about this a bit more: every layer (including but not limited to the default/root layer) has the potential for both direct style-rules and nested sub-layers. So this feature might be useful in nested context, not only in the root/default situation: @layer one;
@layer;
@layer one {
@layer two;
@layer;
} On the other hand, the root/default layer is the only place where authors might not be able to add explicit layering – for the sake of backwards compatibility. Once styles are layered, there is no harm in layering them further. So from that perspective, control is only needed for fully-unlayered styles. Is it confusing if authors can specify different defaults inside each layer context? Is it more confusing if this only works at the top level, and does not work in nested contexts? |
It would be a shame in my opinion if it didn't work the same in nested layers. I'm also not sure how |
The CSS Working Group just discussed
The full IRC log of that discussion<emilio> topic: Allow authors to explicitly place unlayered styles in the cascade layer order<emilio> github: https://github.com//issues/6323 <emilio> miriam: this one is another coming from an earlier resolution <emilio> ... we resolved that unlayered styles are lower pri <jfkthame> present- <emilio> ... jen asked about whether it'd be useful to tweak the unlayered styles priority <emilio> ... there's some syntax proposals in the issue <Rossen_> q? <emilio> ... and I'd expect it to work at each level of layering <emilio> ... are we happy with an empty layer rule syntax? Does this become too complex? <emilio> florian: I could see use cases for top/bottom, has any non-theoretical use case come up for in the middle? <emilio> miriam: yeah, you want components at the top and resets on the bottom, so you might want most of your styles between them <emilio> TabAtkins: Like florian I see the use case but I'm not sure we need to solve it right now <emilio> ... we could resolve the CSS wide keywords as layer names in case we want to solve them <emilio> miriam: does that become a problem if additional wide-keywords are added? <Rossen_> ack fantasai <emilio> TabAtkins: theoretically? But we haven't added many over the years <TabAtkins> s/resolve/reserve/ <emilio> fantasai: we could also do something that isn't a keyword <emilio> ... I don't have strong opinion on having to solve this now, and I'd be ok reserving the wide-keywords <fantasai> s/keyword/keyword, like an asterisk/ <emilio> florian: maybe I need to re-read the minutes for when we decided to switch top/bottom, I wasn't there and it seems !important could take care of jumping to the top <emilio> miriam: main reason for that was that putting them at the bottom allows progressive enhancement <emilio> ... sort of like when not all browsers had media queries you'd write the specific styles in there <emilio> ... but lots of people think of layers as a way to hide their resets <emilio> florian: I guess I see it more like the later but that also doesn't give me a strong use case for having unlayered styles in the middle <emilio> ... I'd be fine reserving the wide keywords though <emilio> fantasai: so there's the question of whether we add it now, if we don't we might want to just reserve the keywords <emilio> miriam: if we're not sure if it's needed I'd be ok with reserving the keywords and delaying <emilio> ... since it adds a fair amount of complexity <emilio> florian: what do we need by reserving the keyword? Just making them syntactically invalid? <emilio> fantasai: yeah, if you define @layer with that keyword the whole block is in invalid <emilio> florian: is that progressively-enhanceable? If you add a layer that doesn't work and then it starts working... <emilio> fantasai: why would you type it in if it doesn't work? <emilio> florian: would it be wholly invalid or just ignored? <emilio> TabAtkins: could we bring that detail back to the thread? <emilio> Emilio: fwiw it seems simpler to make the whole block invalid at parse time <emilio> RESOLVED: Reserve the CSS wide-keywords (making the whole layer block invalid at parse time) for now and details TBD when we have better use cases |
Given the resolution above, I think we all agree that I'm not sure, but I suspect making the whole rule invalid is safer. Otherwise, we might have people who introduce a |
I'm happy with that approach, and drafted some spec language around it. Not sure if we need to get an official resolution, or not? |
I noted while thinking about this in the context of #6284 that explicitly pinning "initial" as a layer name isn't very convenient, because this has to happen once, and so that first declaration needs to be aware of all the layers that need to be above or below the initial layer (which might not be possible if you are using themes / unrelated add-ons). Another approach I have been thinking about is to have two lists independently, all layers that must be above the unlayered styles, and all who need to be below. A strawman would be as follow (`!important following an at-layer name means to put in the list after unlayered styles):
That would yield the following order for the layers : Adding |
The advantage I see is that we are not prescribing anything here about the specifics of the default, authors can get one or the other depending on their needs. |
I think it's going to be useful and important to be able to have one-off layer declaration blocks that are above or below the default-layer styles, so we should have a syntax built into the @layer rule that says whether it goes above or below. Something like:
where
|
I like the goal here, but have a few questions. As I understand this, we would basically be creating two layer stacks — one above and one below the default — and then use the keywords to append layers to the top of either stack? What's the result of these cases? @layer up one;
@layer down one; Does that give us two layers with duplicate names (upper one & lower one)? Or do we only allow this keyword when the name is first used (in which case the second rule is invalid)? Another option is that we only provide this one-off syntax for truly one-off unnamed layers? In which case we likely need both the explicit placement, and the one-off option.
I assume we don't want to allow moving layers around retroactively, so the second rule should not impact the layers defined in the first rule. That's what |
Just a nit: it would be more clear to use something like
I think this is not a problem if the first-party stylesheet already declares the layer order including the unlayered ( |
Quite frankly I think resolution from Issue #6284 was the wrong path to take and has led this discussion to more complex solutions.
Giving unlayered styles the highest priority is not progressive enhancement. A developer setting layer order is intentional and should be given higher weight. Giving priority to unlayered styles makes it difficult to use CSS layers going forward especially if you are unable to control the unlayered order or there is a large amount of legacy CSS . I outlined this in my comment above. Update 7/5/2026: |
This comment was marked as outdated.
This comment was marked as outdated.
One AMP developer supporting our decision after the fact is not a sign that we made this choice for AMP - or even for framework authors generally. That was not at all the deciding factor, or even a main consideration. I have also never heard of that lib, but I'm glad the feature works for them. We also didn't make the decision because of author habits. It's very strange in a multi-mega-thread conversation to suggest that two off-hand comments were the only or main considerations. If you want me to explain why we actually chose this approach, I can (in the other thread). Either way, that ship has sailed. Still, it would be useful for authors to have some additional controls. Over the course of this thread, we've seen a range of use-cases mentioned. But at this point we're almost completely re-treading the same ground over and over, with new people. There are three approaches that keep coming up (with minor variations of syntax). All of them have potential, and all of them have issues:
In practice, I think @kizu's suggestion for option 3 here supports all the At this point, that would be my strong favorite. |
One benefit of |
Just to put credit where it is due, the first mention of this was in @FremyCompany's comment, but yes, re-reading the discussion now, I still think something like And, I don't think there should be any implementation issues — it is just an ability to add one layer above the unlayered styles inside any other layer, including the topmost one. Can we add this to the agenda? (cc @astearns) If we could resolve on this, and if the browsers will implement it, it could be a quick win. A late one, but nevertheless. (I still find myself wanting to use this feature all the time when writing custom overrides for various sites; and if we had it in browsers today, that use case would be covered immediately). |
I've been watching this issue for some time, and I'm failing to see how the Let me share some context. For a WordPress, We have a number of implicit layers today that are mostly definited using specificity.
Also plugin authors can inject random CSS where we don't really know which layer the layer. We think that the unlayered styles that we basically don't control (so can't change them at all) should probably go between "theme" and "block styles" or potentially between "block styles" and "user layer" which means that there are potentially two to three layers that should precede the "unlayered" layer. How do you think this could be handled. |
@youknowriad I don't think any of the proposals will cover your use case? Given unlayered styles is a monolith, you can't have something that goes in between its parts, unless you wrap the whole preceding part with an The But regardless of which solution will be chosen, using any layers at all will lead to the same backward compatibility issues, right? If you'd want to move forward, then one scenario could be: introduce a setting that will make WordPress wrap your current lower implicit layers with explicit ones. Let's say you'd select the Reset and Theme to go below unlayered — you could start from separating those. When If you can describe how a different proposal covers your use case better, please do! |
I was not thinking about adding parts of the same layer in-between other layers, but more thinking that the following would produce the less disruption for us.
or alternatively
The
yes, I believe so, the question I guess is which would result in the minimum breakage and to be honest only experimentation will help us figure it out. What's clear is that the unlayered layer having the smallest or the highest priority probably won't work for us.
If I'm not you're suggestion that theme and reset use the same layer but that's not something we want, we do want these to be separate layers, one taking precedence over the other. |
The There is no functional difference between @layer reset, theme, !unlayered, blocks, user; and @layer reset, theme, !overrides.blocks, !overrides.user; The only difference is what is explicit: the mention of the unlayered styles, or the mention of the styles that go on top of them. (Which is actually a good thing to clarify in the specs: it should be possible to define the order of layers inside |
Thanks it was not clear to me that overrides can be applied to multiple layers, I thought it was just a hidden layer after the "unlayered" one (based on some comments above). Thanks for the clarifications. |
A 4th option would be a new at-rule keyword to indicate that the added layers are “strong layers”. These strong layers stack on top of unlayered styles. We could do something like @layer reset, base;
@layer! components, overrides; The resulting stack – from low to high – becomes Advantage of this new at-rule keyword is that authors can feature detect it ( |
@bramus Does this mean that we couldn't mention the strong layers in the “short” notation when adding styles to them? @layer foo {
@layer! bar {
}
} no longer could be shortened to something like I also like the explicitness of the And we still should be able to detect their support with |
Option 1 avoids unnecessary duplication by specifying By the way, the exclamation mark at the beginning of the naming of each option looks like it would wash them away from the fact that there are reserved names in the specification for future compatibility, and thereby discourage from choosing option 1. |
I was originally thinking that names shouldn’t be affected by that layer being strong or weak, so that layer would be shortened to However, I can see now that it can get complicated. If you do Tweaking that to become So yeah, that |
Is there a reason why "unlayered" should not be a keyword to represent the placement of the unlayered styles in an This seems easy to read and understand. It goes from lowest to highest
or
and if you don't specify the unlayered in the definition it works as it currently works
|
@mcareydsgn there are two reasons we might not want to go that way:
Getting the right name is essential, but first we have to make sure we agree on how the feature should work. My goal for having this on the agenda would be to choose one of the three or four rough approaches – and then we could focus on the exact naming details from there. |
I also like option 3 because it creates a symmetry between this and #10094. And it can be made even more intuitive with symmetric names like To refer to this whole feature without using any syntax from any of the options, I will use the term "post-unlayered styles", since the goal is to allow layered styles after unlayered styles. (Hopefully this helps instead of adding even more confusion). Putting aside bikeshed concerns, I would like to get clarity on two points:
|
|
So, maybe I'm just missing something, but can't It does feel a little weird that no such extra nesting has to be done with layers below unlayered styles, but from a practical view, I don't see how these two proposals differ much if at all. The only thing is, I don't remember if Just one extra thought: I feel like That would get us to something like: @layer important!.code-font {
code { font-family: monospace }
} which to me both looks nice enough and should cover most use-cases I can think of.
I can see cases where one CSS author might inject rules into another author's layer for customisation that should be overridden, so it makes a lot of sense to define every layer to implicitly have a nested |
Yes, this was covered above ("There is no functional difference…").
This was also covered above.
I don't see how In any case, I'm not denying that it can be useful; I'm just concerned about the complexity. See also Tab's comment in #10094 (comment) ("I don't think named layers need an |
I was thinking regarding the “should every layer have its override (and possibly defaults) layer?”, and there are valid use cases for both having a way to place something before/after everything in some layer, and having a way to put something before or after globally. So, we have several different cases:
But I would suggest us to focus on the 1 in this issue, and create separate ones for 2 and 3 (edit: there is already #10094 for 2, though with some parts of 3). I think all of these have valid separate use cases, but 2 is more of a “good to have”/“syntax sugar”, and 3 needs more thoughts (should it be Outside the bikeshedding of the |
Since it's a mega-thread, re-added to the agenda, I will repost a few things. The primary use-cases are:
The three general approaches that have been proposed – each one with various naming options:
I don't think option 1 is really viable here, so we're likely discussing variations on option 2 or 3. If people have additional use-cases, or new syntax ideas, feel free to note them here. But try not to rehash all the earlier debates on existing proposals. I don't know that we'll make a decision from straw-poll here, but it might be interesting to know if people have favorites. Feel free to react with one of the emoji above (yes I chose the frown for option 1 🤷🏻♀️). |
Just a quick thought that might be worth considering: in the case where every layer has an implicit It definitely makes sense to me; if someone else has already put their own styles in the This obviously doesn't apply in the second use-case where I am the first author introducing layers into the project. |
I think so yes, though I don't love the thought of |
Regarding CSS Cascade 5 (cascade layers), @jensimmons commented on another thread about layer ordering:
By default unlayered style come first (lowest cascade priority) in the source order, but this would allow more explicit placement. Roughly (pseudo-code):EDIT: That's no longer the case. In #6284 we reversed the behavior, and now unlayered styles have the highest priority. This explicit placement would still be useful, since there are use-cases for both approaches.
I think that feature makes a lot of sense, and I would likely use it as an author. A few considerations to keep in mind, as we develop a mechanism for this:
The text was updated successfully, but these errors were encountered: