Lit
02 / 02

Shadow DOM, Custom Events & Cross-Framework Use

Lit: Shadow DOM, Custom Events & Cross-Framework Use

Shadow DOM Encapsulation

  • LitElement renders into a Shadow DOM tree by default -- real DOM and CSS encapsulation.

  • A component's own <style>/css`` block won't leak out and affect the rest of the page.

  • Page-level global CSS won't accidentally reach inside and style the component's internals.

  • This is a browser platform feature (part of the Web Components standard), not something Lit invents.

Communicating Out: Custom Events

// The standards-based equivalent of a callback prop -- dispatched
// via the native DOM CustomEvent/dispatchEvent API, so ANY parent
// (Lit, React, Vue, plain HTML) can listen with addEventListener
class ItemPicker extends LitElement {
  private _select(id: string) {
    this.dispatchEvent(new CustomEvent('item-selected', {
      detail: { id },
      bubbles: true,   // propagates up through the DOM
      composed: true,  // crosses the Shadow DOM boundary
    }));
  }
}

// Consuming from plain HTML/JS:
// document.querySelector('item-picker')
//   .addEventListener('item-selected', (e) => console.log(e.detail.id));

// Consuming from React (via a ref, since React doesn't auto-map
// custom events to props):
// <item-picker ref={(el) => el?.addEventListener('item-selected', handler)} />

Cross-Framework Design Systems

  • A Lit component compiles to a real Custom Element -- usable in React JSX, Vue templates, Angular templates, or plain HTML with no framework-specific integration needed.

  • Common motivation: one shared component library serving multiple product teams on different frameworks, instead of maintaining separate React/Vue/Angular implementations of the same button/input/modal.

  • Templates (html``) are standard JS tagged template literals -- no JSX-style compile step required to interpret the syntax, though bundling/minification is still typically used for production.

lit-html vs LitElement, and SSR

  • lit-html: the lower-level templating/rendering engine -- usable standalone (render(html`...`, container)) without the full LitElement component model.

  • LitElement: builds a complete reactive component model (properties, lifecycle, Shadow DOM) on top of lit-html.

  • Lit SSR: renders templates to HTML server-side (faster initial paint, better SEO), then hydrates client-side -- the same general pattern as Next.js, applied to standards-based Web Components.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free