0

When I asked Google AI it responded:

Why combining them is wrong

The selector :host::part() attempts to mix these two concepts incorrectly:

  • It tries to select an element with part="base". This can only be done from the component's consumer.
  • However, it's chained to :host, which can only be used by the component author from inside the Shadow DOM.

Since ::part() is only visible to the host's parent DOM, and :host is only visible from within its own Shadow DOM, the two selectors operate in entirely separate scopes and can't be combined. It's like a house trying to paint its own outside wall from the neighbor's yard.

But then I saw this pattern all over Microsoft's homepage microsoft.com and wondered if there's ever a good reason to use it. Here's an example -

:host::part(tab-item__content) {
    display: var(
      --ds-tab-item-content-display,
      ${t(e.contentDisplay)}
    );
    flex-direction: var(
      --ds-tab-item-content-flex-direction,
      ${t(e.contentFlexDirection)}
    );
    gap: var(--ds-tab-item-content-gap, ${t(e.contentGap)});
    align-items: var(
      --ds-tab-item-content-align-items,
      ${t(e.contentAlignItems)}
    );
    width: var(--ds-tab-item-content-width, ${t(e.contentWidth)});
    max-width: var(
      --ds-tab-item-content-max-width,
      ${t(e.contentMaxWidth)}
    );
    font-size: var(
      --ds-tab-item-content-font-size,
      ${t(e.contentFontSize)}
    );
    font-weight: var(
      --ds-tab-item-content-font-weight,
      ${t(e.contentFontWeight)}
    );
    ...
  }
2

1 Answer 1

8

Is ":host::part()" a valid CSS selector?

Yes, it is valid; but note browser differences in screenshots below.

I presume Microsoft

  • started with ::part(header)
  • noted the difference between FireFox and Chromium output (confirmed FireFox bug)
  • then "fixed" it by adding :host

But... even if you are Microsoft. Why would you want to write:

:host::part(header){background:green}

when you can write the same as:

[part~=header]{background:green} (~ required when there are multiple part names)

Maybe they do not know the ~= attribute selector?
or maybe they are after extreme GZip compression, not using [ ] * characters

Note: only using ::part is a bug in FireFox, the combined :host::part is (I presume; since all browsers behave the same) valid code, but verbose.

Like your AI answer says (with a different metaphore)

:host::part(television){--channel:42}
Is like getting up from your couch,
walking out the door with the remove control in hand,
to switch the TV channel from outside your house/host.

<script>
  customElements.define('css-part', class extends HTMLElement {
    constructor() {
      let style = 
        `:host{display:inline-block;font:11px arial;padding:1em;background:green;color:gold}` +
        `::part(header1)     {background:red}` +
        `:host::part(header2){background:blue}` +
        `[part~="header3"]   {background:deeppink}`; // can be written without "
      super()
        .attachShadow({mode:"open"})
        .innerHTML = `<style>${style}</style>` +
          `<h1 part="header1">Hello Web Component</h1>` +
          `<h1 part="header2">what is your displayed</h1>` +
          `<h1 part="header3">background color?</h1>`;
    }
  });
</script>

<css-part></css-part>

FireFox (bug) Chromium
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.