[css-cascade] Custom Cascade Layers (formerly "custom origins") · Issue #4470 · w3c/csswg-drafts (original) (raw)
This relates to the Cascade Specification, along with a number of "specificity" concerns and proposals (such as #2272 & #3890 & the :where()
selector).
Much of my work with design systems has revolved around helping companies define layers of abstraction: building tokens, then defaults, then patterns, components etc. That's a common approach, whether we call it OOCSS or Atomic Design or ITCSS or something else. In order to do that, we often have to be very careful with matching specificity to layer – so components override patterns, and so on – and third-party tools can easily break a delicate balance.
It strikes me that cascading origins & !important
are designed to solve that same problem on a larger scale (UA, user, author), and then reverse-order for !important
styles. It's a pretty clever solution, but !important
is a blunt instrument for handling layers inside the author origin.
I doubt most developers think about cascading origins, or the role importance plays in it - and at this point they don't really need to for practical reasons. I don't have a full solution here, but a rough sense that providing control of custom cascade origins (within/around the author origin) might help:
- provide a useful tool for solving many issues seen as "a specificity problem"
- help teach the powerful concepts already built into the core of the language
- make it more clear how CSS and
!important
are designed, and how they work under the hood
A few notes on finding a syntax/approach that would work:
- The property-by-property
!important
approach (or!default
proposal which I like) is useful in other situations, but too narrowly applied for this particular use-case - The selector-specificity
:where()
approach is both narrowly-applied and removes all specificity, which could still be a useful tool within origins - I imagine something more similar to a media-query, set in either
@import
or an at-rule of some kind (e.g.@origin
?). That feels like the more proper scope for this problem.
I realize this gets difficult to define quickly:
- Are origins generated with numbers or names? Names feel useful, but would have to be ordered somewhere, and that makes for another layer of complexity.
- What happens when a third-party library contains
@origin
blocks internally, and I want to load it in a specific layer within my overall code. Are there layering contexts, similar toz-index
? Nesting origins would get complicated quickly.
I hope that all makes some sense. I'd be curious for additional thoughts on this, and happy to clarify anywhere I can.