8000 [css-cascade] Evaluate cascade order of ::slotted and global styles in the same conditions · Issue #6466 · w3c/csswg-drafts · GitHub 8000
[go: up one dir, main page]

Skip to content

[css-cascade] Evaluate cascade order of ::slotted and global styles in the same conditions #6466

@jorgecasar

Description

@jorgecasar

Description

According to the spec 3.2.4. Selecting Slot-Assigned Content: the ::slotted() pseudo-element:

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

In a previous conversation (#1915 (comment)), 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.

<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:

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

: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:

: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:

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Regular agenda items

    Status

    Wednesday Afternoon

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0