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 |
I agree with @FremyCompany; changing the order won't help you much, if at all, when @layer rules are discarded in legacy browsers. This is something that should be addressed with a CSS compiler, if that's a need, and luckily the feature that makes it reasonable to do so ( |
What I had in mind was the inverse of current promoted approaches, namely: keep the resets and base styles unlayered, and instead layer up the rest of the author styles (giving them a higher priority than the unlayered styles). That way:
This approach wouldn't require any jumping through hoops by authors, nor the use of a build step. It just works! With this, an author can also decide for themselves whether they want to layer 3rd-party styles or not. Should the specificity of the 3rd-party CSS conflict with their own styles, then it would be recommended to do so. |
Right, @FremyCompany's point is that this wouldn't, in any meaningful sense, "just work". You're still missing all your layered styles. It seems like you're operating on the theory that this is similar to JS and "progressive enhancement", where you can design a basic experience using older tech (like writing an app using This is much more similar to switching to JS arrow functions over the old |
In some cases missing the layered styles could still give you an acceptable result. I don't wholeheartedly agree with the “All styles must work for a site to work, not just some.” statement as a site can work just fine without any styles at all. But OTOH, yes, I can also see that in other (many? most?) cases it would be feasible to have all styles loaded.
I see. Reasonable explanation. Thanks, for enlightening me on it.
Harsh! 😛🙃 |
Yeah, @bramus your argument is exactly the one that took us back and forth on this a few times - but I think Tab is right that once we accept I also like that the result of that decision (layers decrease importance) acts to push against the common assumption that this will escalate things by making everything more and more important. In any case, we need a good polyfill to offer people. OddBird is starting to look into this, but it's not very far along yet. Always open to contributions (or alternative approaches). |
Sorry, the discussion here is a bit long and I didn't understand it. Is it legal to use CSS-wide keywords in e.g. @import 'foo.css' layer(inherit);
@layer unset {}
@layer revert-layer {} |
@yisibl I don't think that was part of this issue, but no – CSS-wide keywords are not allowed in layer names: https://drafts.csswg.org/css-cascade-5/#typedef-layer-name |
If unlayered rules came first instead of last, then I don't see why you couldn't just use old-fashioned methods to construct a basic reset+layout style that is just barely good enough, then (lazily :P) use the new hotness (layers) to do themes & everything else. Sure, it would be highly unorthodox. But well within the realms of possibility (unless I am missing something). Just as you could choose to define some fundamental/barebones functions in one JS file, Granted, I can't think of a single reason why you'd ever want to do this with JS. But the CSS example is salient & tempting. |
Should we maybe reopen this issue? Or should we open a new one? From what I understand, the initial issue was the one preventing the browsers from shipping this as a feature. Now that the layers have shipped, it is obvious that a bunch of use cases are not covered by them. Both the Candidate Recommendation and the latest Editor's Draft list this as an issue, highlighted in red and linked there. But the issue itself is closed. The initial WG resolution is this:
Note the “(currently)”. I would interpret this as “ok for the first implementation, which we could return later to”. And this was actually the way I did interpret this in the past, and usually looking in the specs, seeing the still-present issue mentioned, I thought that this was a still-open issue. I did bring this issue up recently on Mastodon, where it got some support. The main use cases that interest me personally are style overrides for any sites or apps from outside:
One of the best things of CSS, its first letter — the Cascade — always had this intent of treating the users as those who should be able to write CSS as a way to customize websites. Not allowing the users to have a simple way to override things goes against this intent. While it can be argued that maybe browsers themselves should provide convenient ways of writing user origin styles, in reality they don't. Layers seem like the perfect place to unlock the overridability of the web, and make it more accessible for everyone. I acknowledge that it is not as easy to decide how exactly the ability to add layers that go above unlayered styles should be defined, but I strongly think that we require this ability. |
I don't think the problem here was a lack of use-cases, but the fact that we couldn't find a good path forward. I'd be happy to have this open again for more proposals, but I don't think it's a simple problem with a clear solution. I'd also point out that user styles exist, and browsers have systematically made them harder to access. It sure seems like the problem of user-overrides should be solved in the 'origins' part of the cascade, rather than the 'layers' part? I don't mean to say that technical purity should block a more practical solution, if layers really are the best path forward - but it sure seems like we should look at the user origin first? |
I don't know how CSSWG could impact this: to me this seems like a browsers' UI & UX issue in the first place. The ability to have user origin styles is already specified, the issue is that it is underused. And I'm not even sure if browser extensions can provide user origin styles, actually? I'm not knowledgable into how the whole extensions API is used, if it standartized and if it is even possible to require browser extensions to be able to provide user origin styles. Also, all of this only covers one of the cases: the per-user in-browser overrides, while cases like “we'd want to provide styles for a mastodon instance as a whole as overrides, but not fight with the existing styles' specificity” won't be covered, as this is much closer to the layers idea. |
On the one hand CSSWG can't tell browsers what features to implement. On the other hand CSSWG is mostly browser vendors. Maybe more to the point, user styles are (currently) designed for a more 'preference'-like use-case, which browsers do support through limited GUI forms. To do real custom overrides from the user origin, you'd be back in the world of
Yep. Totally. But to back up through some of the previous discussion here, and maybe reframe the feature request… Assigning unlayered styles a universal-but-custom priority is what causes many of the issues, because 'unlayered' is a shared default. Usually, each stylesheet can namespace its own layers, and avoid conflicts when needed. But you can't name a layer that isn't there, and you shouldn't be moving around a layer that every other stylesheet treats as a default. Change its position for one stylesheet, and it breaks for others. If every stylesheet has the same layer, it's the default layer, and anyone can move it around…? That gets pretty confusing and unreliable. But the ability to layer a stylesheet is localized, it doesn't impact other unlayered styles, and it doesn't even impact the relation between layered and unlayered styles inside that stylesheet. Stylesheets remain internally consistent, even when layered on import. So it's already possible to position unlayered styles in the cascade layer order, right? The solution to unlayered styles might just be… layering those styles? For the individual user cases, I think that should be possible for JS to do on the client side? Which an extension would be perfect for, since it can guarantee layer support. And applications like mastodon and wordpress can start layering their own styles, if they want to expose customization features to their users? I hope they do! I know Wordpress has active discussions about it. So then the question might be: can I as a masto admin override what Mastodon provides as part of their app? Which… I'm not sure if that makes sense as a CSS feature? Isn't that a feature request on the applications themselves? |
Yes, but if you old browser doesn’t understand layers, you’re screwed and you end up with no styles at all.
Problem is when your application – be it Masto, WordPress, or whatever – does not use layers, you are prevented from using layers at all to add some extra overrides. You must use unlayered styles from that point on. Personally, what I’d love to see is a simple way to say “this is a layer, but it wins from unlayered styles”. No need to reorder any existing ones or finely control where the unlayered styles should go. In some thread about E.g. @layer! a, b, c;
@layer d, e, f;
@layer! g { … }
@layer h { … } … would leave you with this order (ranked from high priority to low priority): g, c, b, a, unlayered, h, f, e, d. |
That's conceptually like the up/down proposal earlier in the thread, just a different syntax for it. Which then morphed into the slash-syntax that we brought up for debate. It means we're tracking two distinct layer orders (the top one and the bottom one). That was rejected last time we discussed, with concerns for the complexity of nested layers, and interactions between layers from different parts of a large style system. Which is what I've been trying to get at here. How much combinatorial complexity and arms-race-for-importance are we willing to accept? To move a proposal forward here, we have to not only show a syntax that could work to solve these use-cases, but also show that it doesn't cause a lot of potential new issues. Can we do this and avoid the complexities of z-index, or the arms race of importance? Have we considered what happens when third-party tools do this internally, and then we import those tools? |
After some thoughts, my idea: what if we'd have a single, system layer which could be used to place other layers after the unlayered styles? Let's say this system layer would be named What this would mean:
I first wrote the comment above, then re-read the issue and found @FremyCompany proposing basically the same in a comment above I didn't see many reservations in the discussion after that proposal, so I would say this one is probably the one I'd want to see? It would cover most (if not all?) cases for placing styles after the unlayered styles, does not introduce a lot of complexity, and so on. I don't think the Edit: I did write a small blog post about this proposal, and about some other use cases for how I could use it if I would have it — https://blog.kizu.dev/layer-overrides-update/ |
Yeah, that does simplify things. I started writing a response, and then saw I had said all the same things above. The main downside I see is the nested potential for (That and my more general fears about authors reaching for more power turning into a layer arms race, but that fear may be unwarranted. Managing the priority of styles is the entire goal here.) I agree |
I don't think I see issues outside the verboseness? The library/styles author would have to decide over how they would want to place and name their styles — if they're ok with the verbose naming for overriding — fine; otherwise they could always have a Moreover, could potentially be alleviated a bit by choosing a shorter name like, I don't know
Given the power that layer gives is isolated to its parent layer, and only makes sense when thinking about unlayered styles, I don't think it will be an issue? And the verboseness of the syntax could be a slight deterrent there. Maybe we could even then name it I think this is a case where we want to achieve a complex thing, and it might be ok to not provide a simple solution. But I really feel that we need a solution, and I, as an author, would be happy with almost anything :) |
Would this also help solve the use-case of a site refactor, or transition to using layers? The process I imagine would be something like importing a new stylesheet into the 'override' layer, and working within that layer until the old styles can be removed. (tho I suppose that's not much different from importing the old styles into a less powerful layer) Is there potential for people to see this as a form of 'progressive enhancement' where broad defaults 'should' be un-layered for older browsers, and then more detailed styles are layered on top, and only work in modern browsers? Even if that happens, I suppose – with most styles written in the override layer - we still don't have the issues that came with defaulting unlayered styles least powerful. That approach meant the only way to override a third-party layer was to layer your own styles. But with this approach you can still nest third-party 'override' styles into a layer below your own un-layered styles. The 'override' behavior can be scoped like any other layer, and doesn't necessarily impact every other stylesheet. |
Yes, all as you say — this would solve the refactoring case, and I can see the “progressive enhancement” case as well. Having the basic styles available everywhere would be so nice! And, as you said — when we could remove the unlayered styles outside our override layer, it would be simple enough to “unwrap” it, and to continue using just regular layers. Or keep it, and have all the basic styles as is. |
This is very much needed for a "reset" / "base styles" cascade layer to even be usable in a real-world scenario (i.e. where it's pretty much impossible to guarantee that every CSS rule used by the document is inside a cascade layer). |
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):
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: