-
Notifications
You must be signed in to change notification settings - Fork 687
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 |
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 |
The CSS Working Group just discussed
The full IRC log of that discussion<TabAtkins> miriam: since we introduced layers, we intentionally made them weaker than unlayered styles<TabAtkins> miriam: this is useful for importing third-party code, if they use layers you should be able to determine if they override you or not <TabAtkins> miriam: but authors would like a way to be more explicit, there are some cases where it woudl be helpful to import unlayered and override them <TabAtkins> miriam: there are cases where you're getting styles from a third party that you can't layer <TabAtkins> miriam: difficult to solve. three approaches that have come up in various forms <TabAtkins> miriam: if we could at least narrow on the appraoch we could bikeshed the syntax <emilio> q+ <TabAtkins> miriam: 1) somehow say in your layer ordering, give a special name to the unlayered styles and let you put it in yourself <TabAtkins> miriam: conceptually simplest, but now different stylesheets can disagree about position. once you set it once, later things can't move it around. so styles can't palce themselves in relation. <TabAtkins> miriam: think we shoudl take it off the table <TabAtkins> miriam: other two are variants <TabAtkins> miriam: 2) with each layer, say whether it's above or below the unlayered styles <TabAtkins> miriam: ideally make that clear in the layer name itself <TabAtkins> miriam: maybe a ! <TabAtkins> miriam: downside is now we're trakcing two layer lists separately, a little complicated mentally <TabAtkins> miriam: mayb ealso impl complicated, unsure <bramus> I like to call these “strong layers” <TabAtkins> miriam: 3) simplification of that, one named layer that's above and you can add sublayers to that <bramus> q+ <TabAtkins> miriam: call it !top or something, you can write `@layer !top { @layer my-foo {...}}` <TabAtkins> miriam: that seems in some ways a good balance of the tradeoffs <astearns> ack emilio <TabAtkins> emilio: i agree we don't want #1 <emilio> https://github.com//issues/6466 <TabAtkins> emilio: this also interacts with this issue (above) <TabAtkins> emilio: where one potential option was letting unlayered styles compete by specificity across scopes <TabAtkins> emilio: i dont' think this has been discussed yet, but it's similar-ish <astearns> ack bramus <TabAtkins> (I don't think this touches directly on the slotted stuff, even if we end up having to define a similar solution) <TabAtkins> bramus: big +1 on solving this, authors are struggling with it <kizu> q+ <TabAtkins> bramus: i lean towards option 2, has some identifier added to the layer name indicating it's a "strong" layer <TabAtkins> bramus: ! is fine, whatever <TabAtkins> qq <TabAtkins> q+ <TabAtkins> bramus: with the ! you can add a strong layer into a non-strong layer <TabAtkins> astearns: do we allow ! in layer names right now? <fantasai> +1 to bramus <keithamus> q+ <TabAtkins> TabAtkins: no, they're idents <astearns> ack kizu <TabAtkins> kizu: big +1 <TabAtkins> kizu: i'm for third option <TabAtkins> kizu: second can be a bit confusing, because ordering layers is odd if you mix layers with ! and without <TabAtkins> kizu: I think just giving each layer a !top layer is simplest to implement and understand <TabAtkins> kizu: use-cases for this probably isn't that many, so only having one !top per layer is fine imo <TabAtkins> kizu: and each layer has its own seaprate !top <fantasai> scribe+ <astearns> ack TabAtkins <fantasai> TabAtkins: I also now think #3 is best, because ordering problem where the "below" styles and the "above" styles are tracked in the same layer declaration and multiple declarations stack <fantasai> TabAtkins: that induces a misordering, where you have regular, !strong, regular, !strong -- look like they're in a single list but interwoven <bramus> q+ <fantasai> TabAtkins: having an explicit layer avoids this issue, nothing gets reordered in an implicit way <astearns> zakim, close queue <Zakim> ok, astearns, the speaker queue is closed <astearns> ack keithamus <TabAtkins> keithamus: at github we just shipped layers, we ran into this issue so big +1 <romain> q+ <TabAtkins> keithamus: i think option 3 works, option 2 is a little onfusing, option 1 sin't great <astearns> ack fantasai <TabAtkins> fantasai: making sure i udnerstand <TabAtkins> fantasai: option 2 is the name, depending on ! or not, grows the layer order away from teh unlayered <TabAtkins> miriam: no they both get strong <TabAtkins> fantasai: okay so two lists <TabAtkins> fantasai: and #3 is the same but the top list has a name <astearns> ack bramus <TabAtkins> Note my example: `@layers foo bar !baz qux;` <TabAtkins> bramus: replying to Tab about mixing layers <TabAtkins> bramus: could say that when defining, can't intermix <fantasai> fantasai: Ok, in that case I would prefer #2. Prefer that to having a magic name. <TabAtkins> bramus: so only `@layers foo bar; @layers !baz !qux;` <TabAtkins> miriam: can we reject option 1 at least? <TabAtkins> astearns: objections? <romain> +1 <TabAtkins> RESOLVED: Reject option 1 <TabAtkins> Note that "just don't allow mixing in the same statement" is more complicated than it looks. |
Won't option 3 just lead to the same kind of conflicts as we see with What I like about But with option 3 we would introduce a mechanic that again wins over everything.
While with option 2 it we still leave the option open to place other layers before or after the "strong layers" that might be coming from other sources. I agree that declaring the order of layers becomes a lot more confusing. |
With both options 2 and 3, the assumption is that you can nest these 'top' layers (see my previous comment) – and they only override the unlayered style within their layering context. So when importing a 3rd-party stylesheet that uses either If we're not able to further nest third party styles, we can in both cases go farther. This is what leads to the potential for either In other words, these two proposals function the same - and come with the same risks of escalation. The only difference is in whether or not we give the top stack a shared layer name that you can add sublayers to, or we let you add those layers to an unnamed top stack using some syntax. |
Really option 3 only exists as a way of trying to clarify "there's a second stacking of layers up here, we've given it a name". Otherwise they are identical as far as I can tell. |
Yes, I think the While, when importing, yes, we can import something into another layer, thus placing it in the desired order, this is only possible if we control over how we import things. A use case with custom user-styles for a website would, indeed, need do Thinking a bit about it: I guess, we already can mix and match the layers including the nested ones: https://codepen.io/kizu/pen/OJKOLOV @layer bottom, top.foo, whatever, top.bar;
@layer top {
@layer bar {
.test { background: lightgreen }
}
@layer foo {
.test { background: pink }
}
}
@layer bottom {
.test { background: red }
} Here, This is not really different than So, I guess, I'm now slightly more convinced with the option 2. |
Ah, yes, you could indeed use This feels less nice than being able to assign a specific order upfront. |
Another bonus for option 2: if the styles are append-only, then just putting the While with the option 3, with a single |
In the call I brought up some potential confusion caused by being able to interleave top and bottom layers, and the UA having to resort them, like But thinking about it more, this isn't a new problem. It's already the case that the list gets resorted in some cases: if you write Further, in practice the only difference between Option 2 and 3 is the length of the "this is a top layer" sigil. There's actually nothing distinguishing (And yes, the "infinitely nested !top layers" thing is an issue; I don't think we want it, so we'd have to syntactically disallow putting rules directly in a top layer; in other words, So yeah, never mind, I'm all for Option 2 now. I just suggest spelling it somewhat more obviously, like with |
I don't think we can make the That would mean that you couldn't encapsulate some styles by importing them into a layer you control, as the topmost layers will escape it. And if the Basically, if we write a stylesheet and put some layers above the unlayered, we are only concerned about the order of styles we control. But our stylesheet could be imported into a layer inside another stylesheet, meaning the top layer will be only local inside the imported styles, and in the same way you could mention regular layers, we'll need to mention the top layers. |
Yes, I believe these things are all true:
And so the advantage of option 3 (if people want it) is only that we are re-using a nesting syntax to clarify that the re-sorting behavior acts similar to nesting layers. (Edit: Using |
I think you misunderstood what I meant. I was saying that we'd make
Not quite; those characters form valid syntax in both, but mean different things and act differently. You could have top layers named "top" in Option 2, sure, but they'd work like any other named layer, and thus could be targeted and explicitly sorted by preceding code pre-declaring the layer order. A quick But in Option 3, nested !tops always appear at the end of the order on a given layer. No matter what you do, something in |
I can't think of a single case where putting unlayered styles directly in a |
Are we moving towards a consensus here?
|
To those looking: here’s the link with the comment with all options: #6323 (comment)
Would prefer to use |
Definitely +1 to
But to me, |
This is the entire reason I would avoid The way this works is more similar to ID selectors being the stronger of the selectors. |
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: