firsthand

ADR-0007: Light DOM by default, Shadow DOM opt-in

Status: accepted (Phase 1), default to be re-validated with Phase 10 numbers

Problem

Shadow DOM must be supported. Whether it is the default must be decided on measured performance and interop grounds and documented.

Constraints

Options considered

  1. Shadow DOM always. Strong encapsulation, forces every component to carry its own styles, breaks global CSS, adds a root per instance, and requires an element host for every component — which ADR-0003 rejected on cost.
  2. Light DOM always. No encapsulation option at all; fails an explicit requirement.
  3. Light DOM default, { shadow: true } opt-in on components that have an element host.

Chosen design

Option 3. component(fn, { tag: true, shadow: true }) attaches a shadow root and adopts the component type’s constructable stylesheet. Styling across the boundary uses CSS custom properties and ::part. Stylesheets are constructed once per component type and shared via adoptedStyleSheets, never re-parsed per instance.

Performance implications

Memory implications

One shadow root plus one style scope per shadowed instance; one CSSStyleSheet per component type regardless of instance count.

DX implications

Rejected alternatives

Shadow-always (cost, global CSS breakage, forces element hosts everywhere), light-only (fails the requirement).