Skip to content

[css-cascade] Custom Cascade Layers (formerly "custom origins") #4470

@mirisuzanne

Description

@mirisuzanne

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 to z-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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions