Skip to content

Styling Web Components

CSS inside a shadow root is fully scoped — page styles don’t bleed in, shadow styles don’t bleed out. But three mechanisms cross the boundary BY DESIGN: :host / ::slotted / ::part selectors, and CSS custom properties. Understanding which rules stay isolated and which ones intentionally pierce the shadow boundary is the foundation of robust web-component theming.

flowchart LR
  subgraph Page
    PA[".btn color red"]
    PB["::part(label)"]
    PC["--theme-color blue"]
  end
  subgraph Shadow
    SA[":host styles"]
    SB["::slotted(span)"]
    SC["var(--theme-color)"]
    SD["internal .btn"]
  end
  PA -. "blocked" .-> SD
  PB --> SC
  PC --> SC
Shadow boundary — what pierces vs not

This module covers four topics that together give you complete control over shadow-DOM styling:

  1. :host selectors — style the custom element itself from inside its shadow root
  2. ::slotted — target light-DOM children that land in a slot
  3. ::part and exportparts — expose named internals so page CSS can style them
  4. CSS custom properties and Constructable Stylesheets — the most flexible theming approach
Which selector lets page CSS style a shadow-root element by name?
Do CSS custom properties (--var) cross the shadow boundary?
Which selector styles the host element itself from inside the shadow root?