w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.46k stars 658 forks source link

[css-cascade] Opt-in strong proximity for @scope #8601

Open DarkWiiPlayer opened 1 year ago

DarkWiiPlayer commented 1 year ago

The current consensus on #6790 seems to be that weak proximity is generally preferable for @scoped style rules, meaning that stronger selectors from outer scopes can override rules in inner scopes.

I'd like to discuss the merit of adding a mechanism for CSS authors to promote scopes to strong proximity for cases where the alternatives are either much too cumbersome or just not viable altogether:

  1. Layers have a global order in which they apply, so one scope could be made to categorically override another, but that might not be enough when it is unknown to the CSS author which element will be the inner and which the outer scope.
  2. Lower boundaries are only usually viable to scopes of the same type, like @scope ([theme="dark"]) to ([theme]) but are a poor solution for unrelated scope types that want to override similar rules.

One such example that I often encounter when writing CSS is that different sections of a website should have different styles for :links, where a link in a nav is usually identifiable as a clickable link from context, whereas links in paragraphs need to be styled differently (usually underlined and/or different font colour) for the user to identify them as such.

This gets complicated when, for example a nav may appear inside a p in one instance, but a p may also appear inside a nav (in the form of, say, a side-panel brought up by a hamburger button at the end of a nav bar with some text at the bottom)

One proposed syntax for this is an added exclamation mark @scope! (nav) { /* ... */ }, but another obvious option would be a key-word like @scope strong (nav) { /* ... */ }

To keep the discussion on point, I'd ask to not go too deep into is it at all possible to do without this by clever usage of layers and lower boundaries but to focus instead on the actual viability of such work-arounds and whether it's reasonable to add this as an easier and more maintainable way of getting the job done.

romainmenke commented 1 year ago

https://github.com/w3c/csswg-drafts/issues/6790#issuecomment-1471721833

so it essentially just creates a two-class system for styling rules, which is really hard to work with

That was exactly my point in https://github.com/w3c/csswg-drafts/issues/6790#issuecomment-1471517061

Strong proximity scoping might feel similar as @layer but the opt-in or toggle mechanic would again introduce this two-class system, which again would be really hard to work with.

The issue with !important is that some action at a distance changes the rules/context you have to work in.

DarkWiiPlayer commented 1 year ago

But just like @layers, it's not a two-tier system, because you can stack as many of them as you like. While there is no !importantererer, you can always create a new, inner strong @scope that further overrides the rules of the (now) middle scope, and you can always override scoped rules with unscoped rules in a higher @layer, so everything done by a strong @scope is extensible and reversible, unlike !important rules used to be (again, for lack of an !importanter keyword, that was a one-time override).

romainmenke commented 1 year ago

Different two-tier system :)

With !important authors get stuck with why isn't my declaration being applied? Once someone at a distance used !important you are forced to also add !important (specificity still applies). This escalates until you end up with !important everywhere.

The same would be true with @scope. Any mode toggle that makes something have more weight will force others to also add more weight to override the thing that you gave more weight.

How you add more weight is a factor, but it is not the core issue. It is that you have to add weight because someone else (at a distance) added weight.

you can always create a new, inner strong @scope that further overrides the rules of the (now) middle scope

Exactly. It forces others to also use a strong @scope. A weak @scope would no longer work.