demo · v142

Component Library Across Shadow Trees

The pre-Chrome-142 footgun the WG closed: a third-party design-system component ships its own shadow root with @container sidebar (max-width: 300px). The host app declares container-name: sidebar in the light tree. Before this change, the rule inside the shadow root didn't see the outer name and silently fell back. With non-tree-scoped matching, the same vendored component "just works" wherever the host names its containers — what every UI library author was asking for.

light DOM container-name: sidebar

light DOM container-name: main-pane

cross-tree @container resolves
last layout snapshot

Each <vendor-card> attaches a shadow root and styles itself with @container sidebar and @container main-pane. Resize the window: cards in the narrow pane go compact, wide-pane cards expand — even though the rules live inside a shadow tree the outer page never modified.

component code

class VendorCard extends HTMLElement {
  connectedCallback() {
    const sr = this.attachShadow({ mode: "open" });
    sr.innerHTML = `
      <style>
        :host { display: block; padding: 1rem; border: 1px solid #000; }
        /* These names live in the shadow tree but match a light-DOM
           ancestor in Chrome 142+. Pre-141 they silently miss. */
        @container sidebar (max-width: 320px)  { :host { font-size: 0.85rem; } }
        @container main-pane (min-width: 480px) { :host { padding: 2rem; font-size: 1.15rem; } }
      </style>
      <slot>default card</slot>
    `;
  }
}
customElements.define("vendor-card", VendorCard);

see also