Code Reference

Web Components

HTML · Reference cheat sheet

Web Components

HTML · Reference cheat sheet


📋 Overview

Web Components combine Custom Elements, Shadow DOM, and HTML templates/slots into reusable, framework-agnostic widgets. Define a class, register a tag with a hyphenated name, encapsulate markup/styles in a shadow root, and project content with slots.

🔧 Core concepts

PieceRole
Custom ElementscustomElements.define("x-el", Class)
Shadow DOMstyle/DOM encapsulation
<template> / <slot>markup reuse & projection
CSS ::part / varscontrolled theming
ES modulesload component definitions
  • Lifecycle: constructor, connectedCallback, disconnectedCallback, attributeChangedCallback.
  • Form-associated custom elements can participate in forms (ElementInternals).
  • Progressive enhancement: unknown elements render light DOM children until upgraded.
<script type="module">
  class CoolBadge extends HTMLElement {
    constructor() {
      super();
      this.attachShadow({ mode: "open" }).innerHTML = `
        <style>:host{display:inline-pad;padding:.2em .5em;background:var(--badge-bg, #eee)}</style>
        <slot></slot>
      `;
    }
  }
  customElements.define("cool-badge", CoolBadge);
</script>
<cool-badge>Beta</cool-badge>

💡 Examples

<template id="tooltip-tpl">
  <style>
    :host {
      position: relative;
    }
    .tip {
      display: none;
      position: absolute;
      ...;
    }
    :host(:hover) .tip,
    :host(:focus-within) .tip {
      display: block;
    }
  </style>
  <slot></slot>
  <div class="tip" part="tip"><slot name="tip"></slot></div>
</template>

<script type="module">
  const tpl = document.getElementById("tooltip-tpl");
  class XTooltip extends HTMLElement {
    constructor() {
      super();
      this.attachShadow({ mode: "open" }).append(tpl.content.cloneNode(true));
    }
  }
  customElements.define("x-tooltip", XTooltip);
</script>

<!-- Theming from outside -->
<style>
  x-tooltip {
    --badge-bg: #224;
  }
  x-tooltip::part(tip) {
    border-radius: 6px;
  }
</style>
await customElements.whenDefined("cool-badge");

⚠️ Pitfalls

  • Customized built-ins (is="...") lack full cross-browser support — prefer autonomous elements.
  • Closed shadow roots aren’t secure — don’t hide secrets there.
  • Slotted content is styled with limited ::slotted — complex styling may need parts/vars.
  • SSR/hydration needs care — unknown elements flash unstyled without declarative shadow DOM strategies.
  • Avoid huge shadow trees for simple static HTML — semantics first.

On this page