← Concepts

阅读中文版本

Custom Elements

Custom elements let you define new HTML tags with author-owned lifecycle callbacks — upgrade, attribute changes, connection — natively, without framework buy-in.

browser

Definition

Custom Elements is the browser API for registering new element names with a class that extends HTMLElement. The platform calls lifecycle callbacks: connectedCallback and disconnectedCallback on DOM insertion, attributeChangedCallback for observed attributes, and the constructor during upgrade of existing markup. Registry rules enforce name uniqueness and valid dash-containing names.

Context and scope

Foundation for design systems that work across frameworks, embeddable widgets, and progressive enhancement of server-rendered markup. Combined with shadow DOM and templates for full web components.

Common misconceptions

  • The constructor runs when the element appears in HTML — upgrade happens when the definition registers, which may be long after parsing
  • Custom elements require a framework — they are platform-native and interoperate with frameworks as ordinary DOM
  • Observed attributes are automatic — only names returned from observedAttributes fire attributeChangedCallback

Anti-patterns

  • Fetching data in connectedCallback without abort handling on disconnect, leaking requests across navigations
  • Doing heavy work in the constructor, which must remain minimal for parser and clone compatibility
  • Reading attributes before the element is connected and assuming layout or children exist

Related concepts

Related examples

Authoritative source

https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements

What it is

The tag registry is extensible: define a class for my-widget and the platform instantiates it wherever the tag appears, calling your code at well-defined lifecycle points. Markup, CSS, and JavaScript of any stack can consume the element as a first-class citizen.

How it works

customElements.define registers name plus class. Upgrade order matters: markup parsed before definition stays as unknown elements until registration, then upgrades in place. observedAttributes gates attributeChangedCallback; connectedCallback may fire multiple times as elements move in the DOM, so handlers must be idempotent.

When to use it

Cross-framework design systems, drop-in widgets for third-party pages, wrapping legacy imperative components for declarative consumption. They pair naturally with shadow DOM for style encapsulation and with element internals for form participation.

Pitfalls

Undefined elements before script loads cause a flash of unstyled or unupgraded content; plan styling for both states. Moving elements between documents triggers disconnect and connect again. Custom element names must contain a dash and must not collide with existing tags — the registry enforces this at definition time.