[csswg-drafts] [css-cascade] evaluate specificity of ::slotted and global styles in the same conditions. (#6466)

jorgecasar has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-cascade] evaluate specificity of ::slotted and global styles in the same conditions. ==
## Summary

According to the spec [3.2.4. Selecting Slot-Assigned Content: the ::slotted() pseudo-element](https://drafts.csswg.org/css-scoping/#slotted-pseudo):

> The specificity of `::slotted()` is that of a pseudo-element, plus the specificity of its argument.

In a previous conversation (https://github.com/w3c/csswg-drafts/issues/1915#issuecomment-535381522), it was clear and the solution proposed is to use `!important` but I think that the current solution is a bad Developer Experience when you apply it to real life.

Following the definition,`::slotted(h1)` should have a 0-0-2 specificity and `h1 just 0-0-1. Then `::slotted(h1)` should win without `!important`. But it seems they don't fight in the same arena and `!important` is required.

## Example

Here is an that explains better the use case. Taking this HTML as a base. We want to use slots to take the advantage of HTML declaration, for example for SEO reasons.

```html
<fancy-hero>
  <"shado-dom">
    <style>
      :host {
        background: #333;
      }
      :slotted(h1) {
        color: #CCC;
      }
    </style>
  </"shado-dom">
  <h1>My site is awesome</h1>
</fancy-hero>
```

We would like to have some generic styles for headings and paragraphs but the web component would like to restyle them using the `::slotted()` pseudo-element. As there are other h1 in other pages without `fancy-hero` wrapper, we have some generic styles like this:

```css
h1 {
  color: #333;
}
```

Then the color of my `fancy-hero h1` changed to `#333`. The only way to preserve the `fancy-hero h1` style from inside the `fancy-hero` is by applying `!important`

```css
:host {
  background: #333;
}
::slotted(h1) {
  color: #CCC !important;
}
```

But once you do that, it's impossible to change from outside, to make my component customizable. And the only way is to use custom properties like this:

```css
:host {
  background: #333;
}
::slotted(h1) {
  color: var(--hero-title-color, #CCC) !important;
}
```

Then I can customize my `fancy-hero` adding this styles into the global styles:

```css
fancy-hero{
  background: red;
  --hero-title-color: white;
}
```

Extrapolating this use case to a complex component with multiple slots and much more properties, it's not viable. At this point we have two options:

- Use shadow DOM to encapsulate styles, but we lost the light DOM advantage.
- Set `!important` and declare custom properties in all styles properties of my component.

## Proposal

I would like to propose that shadow DOM styles fight with the global styles in the same conditions. The cascade should be applied independently where the styles are defined.

Coming back to the specificity definition`::slotted(h1)` should have a 0-1-1  and `h1` 0-1-0. Then `::slotted(h1)` should win without `!important`. This allows developers to create custom elements more reusable and easy to customize without dealing with thousand of custom properties and fill the code with `!important` in all properties.

## Demo

https://webcomponents.dev/edit/eQFJPlOvQMIuUZj71ohV/README.md

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/6466 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 21 July 2021 07:38:58 UTC