[csswg-drafts] [css-scoping] Consider aligning ::slotted() for fallback content with implementations (#5482)

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

== [css-scoping] Consider aligning ::slotted() for fallback content with implementations ==
The scoping spec states that:

"The ::slotted() pseudo-element represents the elements assigned, after flattening"

According to the flattening algorithm in the HTML spec, that also includes the fallback children of a slot if that slot has no assigned nodes. This behavior was agreed on in [WebComponents issue 631](https://github.com/w3c/webcomponents/issues/631) and issues were reported for Blink and WebKit, but have not been fixed.

The current implementations walk the assignedSlot chain and apply ::slotted rules from each slot's scope, assignedSlot being null for fallback elements.

This is an example of how this works (in all browsers per current spec) with nested slot assignment:

```
<!doctype html>
<div id="host"><span class="a">Orange with blue border</span></div>
<script>
  const root = host.attachShadow({mode:"open"});
  root.innerHTML = `
    <style>
      ::slotted(.a) { border: 2px solid blue }
    </style>
    <div id="host">
      <slot></slot>
    </div>
  `;
  const inner_root = root.querySelector("#host").attachShadow({mode:"open"});
  inner_root.innerHTML = `
    <style>
      ::slotted(.a) { color: orange; }
    </style>
    <slot></slot>
  `;
</script>
```

Per current spec, moving the span into fallback content for the slot should also result in orange text and blue border, but this is unstyled in all browsers):

```
<!doctype html>
<div id="host"></div>
<script>
  const root = host.attachShadow({mode:"open"});
  root.innerHTML = `
    <style>
      ::slotted(.a) { border: 2px solid blue }
    </style>
    <div id="host">
      <slot><span class="a">Orange with blue border</span></slot>
    </div>
  `;
  const inner_root = root.querySelector("#host").attachShadow({mode:"open"});
  inner_root.innerHTML = `
    <style>
      ::slotted(.a) { color: orange; }
    </style>
    <slot></slot>
  `;
</script>
```

If the author wants to style a certain type of element the same whether it is assigned, or fallback, it can be accomplished with the current implementations adding an extra selector like this:

```::slotted(.a), slot > .a```

However, that only works in the scope where the fallback is. For the example above, you can do this for the tree with the border rule, but not when that slot is assigned to the slot of the inner root.

I have done an implementation which matches the current spec in Blink, and it is pretty straightforward. However, compat is a big concern here. The impact of changing the implementation would be hard to use-count/quantify. I've been in contact with engineers at Google working on Web Components and Polymer who thinks that changing this is too risky compat-wise and would prefer a spec change.

This surfaced in a [bug report](https://crbug.com/1119248) from Salesforce which found inconsistencies between implementations, but it turns out that is about ::slotted(slot) matching nested slots in WebKit, while Blink and Firefox do not match those:

```
<!doctype html>
<div id="host"><span class="a" slot="inner">Orange with blue border</span></div>
<script>
  const root = host.attachShadow({mode:"open"});
  root.innerHTML = `
    <style>
      ::slotted(.a) { border: 2px solid blue }
    </style>
    <div id="host">
      <slot>
        <slot name="inner"></slot>
      </slot>
    </div>
  `;
  const inner_root = root.querySelector("#host").attachShadow({mode:"open"});
  inner_root.innerHTML = `
    <style>
      ::slotted(slot) { color: orange; }
    </style>
    <slot></slot>
  `;
</script>
``` 

@emilio @rniwa @gregwhitworth


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


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

Received on Friday, 28 August 2020 09:17:07 UTC