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-cascade-5] Allow authors to explicitly place unlayered styles in the cascade layer order #6323

Open
mirisuzanne opened this issue May 28, 2021 · 113 comments

Comments

@mirisuzanne
Copy link
Contributor

mirisuzanne commented May 28, 2021

Regarding CSS Cascade 5 (cascade layers), @jensimmons commented on another thread about layer ordering:

Would it be possible to allow Authors to set for themselves where in the cascade the "unlayered layer" resides? Maybe they even want to sandwich it in-between. A mechanism that's part of however they define the named layers & determine which layer is "first" & "second", etc.

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.

/* the default behavior */
@layer <unlayered-styles>, reset, framework, components, utilities;

/* placed "in-between" layers */
@layer reset, framework, <unlayered-styles>, components, utilities;

/* placed at the top/end of the layer order */
@layer reset, framework, components, utilities, <unlayered-styles>;

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:

  • I would expect it to be repeatable for implicit sub-layers, as well the implicit outer layer
  • Since all layer names are currently custom-idents, we either need a reserved name, or some way of distinguishing the provided implicit-layer ident from author-provided idents.
@Alohci
Copy link
Contributor

Alohci commented May 31, 2021

Definitely welcome to have that level of control. If you didn't want a reserved name you could use different @ name. e.g.
@layer reset, framework;
@unlayered;
@layer components, utilities;

@fantasai
Copy link
Collaborator

fantasai commented Jun 1, 2021

Idk if it's a good idea, but one possibility would be to just leave out the identifier.

@layer reset, framework;
@layer;
@layer components, utilities;

@mirisuzanne
Copy link
Contributor Author

mirisuzanne commented Jul 5, 2021

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?

@Alohci
Copy link
Contributor

Alohci commented Jul 5, 2021

It would be a shame in my opinion if it didn't work the same in nested layers.

I'm also not sure how @import url(links.css) layer(mylayer); would work if @layer; didn't work the same when it becomes nested by the import as it does when the import doesn't inject it into a layer.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed Allow authors to explicitly place unlayered styles in the cascade layer order, and agreed to the following:

  • 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
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

@frivoal
Copy link
Collaborator

frivoal commented Jul 27, 2021

Given the resolution above, I think we all agree that @layer initial { } is simply invalid and the whole block is rejected. However, what of @layer foo, initial, bar;? Is that whole rule rejected too, or do we simply order foo and bar and ignore the non-existing initial layer?

I'm not sure, but I suspect making the whole rule invalid is safer. Otherwise, we might have people who introduce a @layer initial { } block, fail to notice that that doesn't do anything, order that layer into the middle of the stack with @layer foo, initial, bar;, and some day, if we do make the initial keyword apply in that situation, that changes the ordering of their whole page. I think this scenario would be less likely to happen if we ignore the whole rule, as then the author would be confronted with the fact that the ordering of their foo and bar layer don't work either, making it easier to notice.

@mirisuzanne
Copy link
Contributor Author

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?

mfreed7 pushed a commit to mfreed7/csswg-drafts that referenced this issue Aug 4, 2021
@FremyCompany
Copy link
Contributor

FremyCompany commented Oct 6, 2021

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):

@layer reset { article h1 { margin: 0; } }
@layer theme { h1 { margin-top: 1.2em; } }
@layer special-overrides !important { h1:first-child { margin-top: 0 } }
.main-title { margin-top: 0.2em; } }

That would yield the following order for the layers : reset < theme < /initial/ < special-overrides.

Adding !important to individual values has an effect as usual, the !important on @layer only changes the order of layers in the list, but does not propagate to the values themselves (but the change in order for the layer will make the declaration be more important).

@FremyCompany
Copy link
Contributor

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.

@fantasai
Copy link
Collaborator

fantasai commented Oct 6, 2021

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:

@layer [ up | down ]? <layer-name> { ... }

where

  • up increases the priority of normal rules (and decreases priority of !important rules)
  • down decreases the priority of normal rules (and increases priority of !important rules)

@mirisuzanne
Copy link
Contributor Author

mirisuzanne commented Oct 7, 2021

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.

@layer  <layer-name> | [ up | down ] { ... }

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 up/down imply to me. So if that's not what we mean, I think we should name the two layer stacks, and use their names as the keywords: something more like upper/lower or default/important or …?

@astearns astearns moved this from Regular agenda items to Thursday afternoon in CSSWG Agenda TPAC 2024 Sep 16, 2024
@mirisuzanne
Copy link
Contributor Author

Since it's a mega-thread, re-added to the agenda, I will repost a few things. The primary use-cases are:

  • Being able to override third party styles when we have no way to put them in a layer. This might include internal app styles being overridden by a user.
  • Overriding legacy unlayered code, with newer layered styles. This can be used as part of a site refactor.
  • The progressive enhancement use-case is interesting… But the longer this takes, the less compelling it becomes. 😅

The three general approaches that have been proposed – each one with various naming options:

  1. !unlayered 😕 - (or initial or * or…) - Provide name the 'un-layered layer' so that it can be placed in the layer order like any other layer. While this sounds the simplest in some ways, it leads to issues with coordination across style sheets, and provides no way for later-introduced layers to demote themselves below unlayered styles.
  2. !<layer-name> 🎉 - (or up/down or / or @layer! or…) - Provide a way of specifying for each layer if it belongs above or below unlayered styles. This is very flexible, but complicated to reason about - tracking two distinct layer orders.
  3. !overrides 🚀 - (or !important or !top or…) – Provide a single pre-defined and permanently positioned layer above unlayered styles. In some ways this is a variation on option 2, but maybe simpler to reason about, since it relies on existing concepts.

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 🤷🏻‍♀️).

@DarkWiiPlayer
Copy link

Just a quick thought that might be worth considering: in the case where every layer has an implicit !top layer, would !top.!top be valid?

It definitely makes sense to me; if someone else has already put their own styles in the !overrides layer, and I want to add my own styles to it in a layer that overrides even those, I'd want to use !overrides.!overrides.

This obviously doesn't apply in the second use-case where I am the first author introducing layers into the project.

@mirisuzanne
Copy link
Contributor Author

Just a quick thought that might be worth considering: in the case where every layer has an implicit !top layer, would !top.!top be valid?

I think so yes, though I don't love the thought of !top.!top.!top.!top.!top appearing in style sheets.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-cascade-5] Allow authors to explicitly place unlayered styles in the cascade layer order, and agreed to the following:

  • RESOLVED: Reject option 1
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.

@romainmenke
Copy link
Member

romainmenke commented Oct 23, 2024

Won't option 3 just lead to the same kind of conflicts as we see with !important?

What I like about @layer is that the order of layers isn't fixed.
The "owner" of the page can intervene and always add a list of layer names in their preferred order at the top of their page. This is a really nice "conflict resolution" feature.

But with option 3 we would introduce a mechanic that again wins over everything.
A 3rd party could write all their styles in @layer !important {}, forcing any other styles sharing the same page to at least match that.

@layer !important {} would effectively become the new unlayered styles. So we wouldn't have solved the underlying issue, we would have just moved it around a bit :)

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.
But I'd rather have a feature that is sometimes confusing but also more powerful.

@mirisuzanne
Copy link
Contributor Author

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 !layer-name (option 2) or !top-layer (option 3) we would be able to pull their styles into our own lower-priority layer (e.g. reset) and the result is a layer called reset.!layer-name or reset.!top-layer. It is weaker than unlayered styles at the root, but stronger than unlayered styles in reset.

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 !top.!top.!top or !my-top.!my-top.!my-top.

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.

@mirisuzanne
Copy link
Contributor Author

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.

@kizu
Copy link
Member

kizu commented Oct 23, 2024

Yes, I think the !important.!important is a good argument against a single !top layer.

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 !top.!top, or maybe even !top.!top.!top to put something as “the topmost”, with the option 2 allowing just identifying which layer is the topmost, and then doing @layer !website-top, !my-overrides;. With a flat list of these, you'd need to mention only two layer names — the toppest, and yours, but with the option 3 you'd really need to just dig into the !top.!top.!top etc.

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, @layer bottom, top.foo, whatever, top.bar; can be already kinda confusing, but allowed: we're separately defining an order for the regular layers, and for the layers inside the top layer.

This is not really different than @layer bottom, !foo, whatever, !bar; (well, aside from the whatever in the top example overriding the top one).

So, I guess, I'm now slightly more convinced with the option 2.

@romainmenke
Copy link
Member

Ah, yes, you could indeed use !top.!top on your own styles to override someone already using !top. I overlooked that.

This feels less nice than being able to assign a specific order upfront.
But good that there always is an escape hatch :)

@kizu
Copy link
Member

kizu commented Oct 23, 2024

Another bonus for option 2: if the styles are append-only, then just putting the !my-overrides layer after all the existing, at the top layer, will win over everything, so the @layer !site-topmost, !my-overrides; will be necessary only if your layer goes before the !site-topmost.

While with the option 3, with a single !top layer, you can't just add anything, and it be the topmost thing just based on the order, as the overrides of the overrides go into depth, and you don't know how long the current !top.!top chain is.

@tabatkins
Copy link
Member

tabatkins commented Oct 23, 2024

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 @layer foo !bar baz; actually being equivalent to @layer foo baz !bar;. Bramus had a suggestion about requiring top and bottom layers be specified in different rules, but that doesn't generalize well to nested layers.

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 @layer foo.one bar foo.two;, that's actually equivalent to @layer foo.one foo.two bar;, because sublayers are always grouped by their parent layers. (@kizu says this same thing, above; their comment collided with mine.)

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 foo.!one and foo.!top.one except that in the first the special "this is a top layer" sigil is spelled !, while in the second it's spelled !top.. The extra characters don't meaningfully help distinguish it, so we can just remove them.

(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, foo.!top would be an invalid layer name at the syntax level. But at that point, the !top. characters are even moreso just a five-character sigil for "this is a top layer", since the top layers don't exist on their own in a meaningful sense.)


So yeah, never mind, I'm all for Option 2 now. I just suggest spelling it somewhat more obviously, like with #, which is both "weightier" as a glyph and already indicates important things in a selector.

@kizu
Copy link
Member

kizu commented Oct 23, 2024

@tabatkins
(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, foo.!top would be an invalid layer name at the syntax level. But at that point, the !top. characters are even moreso just a five-character sigil for "this is a top layer", since the top layers don't exist on their own in a meaningful sense.)

I don't think we can make the foo.!top an invalid layer, unless the proposal is to make top-level layers bubble up through regular ones and be always at the top even when they're nested?

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 #top will be local to the imported layer and won't escape, we need an ability to access it through foo.#top. And with option 2, the infinitely nested top layers is not an issue, as you don't need to do !top.!top.!top when you can do just @layer !top, !topper;.

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.

@mirisuzanne
Copy link
Contributor Author

mirisuzanne commented Oct 23, 2024

Yes, I believe these things are all true:

  • layer.!top.something and layer.!something are different spellings of the same behavior.
  • We have to allow these in nested contexts, so either way !top.!top.!top is a valid option.
  • Resorting already happens for nested layers

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 # would make !top.!top.!top invalid 😅 but now we have #top.#top.#top. Jokes aside - I'd be happy with that spelling, since I prefer we don't associate this with importance. The two features will interact more like ids and importance interact)

@tabatkins
Copy link
Member

I don't think we can make the foo.!top an invalid layer, unless the proposal is to make top-level layers bubble up through regular ones and be always at the top even when they're nested?

I think you misunderstood what I meant. I was saying that we'd make foo.!top an invalid layer name to specify; you'd have to write a sublayer after it, like foo.!top.bar; similarly, you couldn't write @layer foo { @layer !top {...}}, you'd have to write @layer foo { @layer !top.foo {...}}. That way, no styles would ever be inserted directly into a top layer; they'd always be nested into a named layer.

We have to allow these in nested contexts, so either way !top.!top.!top is a valid option.

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 @layer !top !my-stuff; ensures that your stuff wins in the layer sorting.

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 !top comes after foo, and even after !top.foo (because the styles are unnested within the !top layer, and thus go at the end); to put your own thing after, you have to exceed their number of !tops and do !top.!top.

@DarkWiiPlayer
Copy link

I can't think of a single case where putting unlayered styles directly in a !top layer would make sense, which would be the only advantage of !top over !my-top

@mirisuzanne
Copy link
Contributor Author

Are we moving towards a consensus here?

  • Accept option 2, with a custom syntax for naming 'override' layers, which are sorted above unlayered styles
  • Use #<layer-name> as the initial syntax (and optionally bikeshed further if needed)

@bramus
Copy link
Contributor

bramus commented Nov 15, 2024

Are we moving towards a consensus here?

  • Accept option 2, with a custom syntax for naming 'override' layers, which are sorted above unlayered styles

To those looking: here’s the link with the comment with all options: #6323 (comment)

  • Use #<layer-name> as the initial syntax (and optionally bikeshed further if needed)

Would prefer to use !<layer-name> for the syntax as the ! has a link with !important.

@benface
Copy link

benface commented Nov 15, 2024

Definitely +1 to !. I don't understand where the # proposal comes from. Well, I see it was proposed by @tabatkins here:

So yeah, never mind, I'm all for Option 2 now. I just suggest spelling it somewhat more obviously, like with #, which is both "weightier" as a glyph and already indicates important things in a selector.

But to me, # implies "ID" a lot more than it implies weight or importance.

@mirisuzanne
Copy link
Contributor Author

mirisuzanne commented Nov 15, 2024

Would prefer to use !<layer-name> for the syntax as the ! has a link with !important.

This is the entire reason I would avoid !. Importance is a distinct feature that works differently. I'm worried that if we conflate them, we only add confusion about the differences. People are already unfamiliar with the reversing behavior of importance, and often surprised by how that interacts with Cascade Layers. I'd very much like to avoid adding to that confusion. These are not important layers. They work different from important layers.

The way this works is more similar to ID selectors being the stronger of the selectors.

@astearns astearns moved this to FTF agenda items in CSSWG January 2025 meeting Jan 27, 2025
@astearns astearns moved this from FTF agenda items to Regular agenda items in CSSWG January 2025 meeting Jan 27, 2025
@astearns astearns moved this from Regular agenda items to FTF agenda items in CSSWG January 2025 meeting Jan 28, 2025
@astearns astearns moved this from FTF agenda items to Friday morning in CSSWG January 2025 meeting Jan 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: TPAC/FTF agenda items
Status: Friday morning
Status: To Consider
Development

No branches or pull requests