Can the CSS :part pseudo-selector be used to style nested web components?
Asked Answered
T

2

6

When creating Web Components with encapsulated styles using Shadow DOM, parts of the shadowed markup can be styled using the ::part pseudo selector (https://developer.mozilla.org/en-US/docs/Web/CSS/::part).

Can the part selector be used to target nested shadow parts?

<custom-element>
  #shadow-root
    <div part="thats-easy"></div>
    <another-custom-element part="proxy-part">
      #shadow-root
        <div part="target-me"></div>
    </another-custom-element>
</custom-element>

Current efforts were fruitless:

another-custom-element::part(target-me) { }
custom-element::part(proxy-part) another-custom-element::part(target-me) { }
custom-element::part(proxy-part another-custom-element::part(target-me)) { }
custom-element::part(proxy-part::part(target-me)) { }
```
Tennyson answered 9/2, 2022 at 10:14 Comment(0)
D
6

Fun twist, it is possible and TIL about exportparts
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/exportparts

Example 1

<style>
  mux-player::part(textspan) { color: red; }
</style>

<mux-player>
  <template shadowrootmode="open">
    <media-poster-image exportparts="poster, img, innerspan: textspan">
      <template shadowrootmode="open">
        <img part="poster img" src="...">

        <span part="innerspan">
          This text will be red because the containing shadow host forwards innerspan to the document as "textspan" and the document style matches it.
        </span>

        <span part="textspan">
          This text will not be red because textspan in the document style cannot match against the part inside the inner custom element if it is not forwarded.
        </span>
      </template>
  </template>
</mux-player>

Example 2

Example in production with multiple nested custom elements with CSS parts.
https://github.com/muxinc/elements/blob/main/packages/mux-player/src/template.ts

Dena answered 19/7, 2022 at 18:45 Comment(3)
Further reading about using exportpartsInextensible
Future readers: My question here demonstrates how exportparts is used with nested components.Inextensible
@luwes, would you mind adding an example of how it works for the code in the question? I think it would benefit future readers to have an example here as well.Tennyson
C
3

Nope. It is not possible. It kind a breaks the encapsulation principle. The right way is to use proper theming. That means using a combination of:

::part - For direct theming of the component
:host-context - for theming based on the context
::slotted - For styling the slotted element inside the styling

For more dynamic theming, you can use above styles in combination with Element.matches API. Whatever the class/context that the user of the component has set, you can then change the styling of nested children component.

On a side note, modifying the styling of a decadent component (children of children) is a bad practice even when not using Shadow DOM or Web Components. It will result in a brittle non-maintainable CSS.

Edit Note:

:host-context is not implemented in all browsers and probably never will.

Coalition answered 9/2, 2022 at 15:51 Comment(2)
Be careful with ::host-context, limited support, see: #61533339\Pulp
@Danny'365CSI'Engelman That is right.Coalition

© 2022 - 2024 — McMap. All rights reserved.