All topics
DOMadvanced

Web Components and Custom Elements

Native browser APIs for creating reusable, encapsulated HTML elements without relying on a JavaScript framework.

Web Components are a set of native browser APIs — Custom Elements, Shadow DOM, and HTML Templates — that let you build genuinely reusable, encapsulated UI elements using standard browser features rather than framework-specific component models. They're less universally used than React/Vue-style components in typical job stacks, but they come up in interviews focused on framework-agnostic architecture, design systems, or lower-level browser API knowledge.

Web Components are like standardized shipping containers: any custom element you build (the container) can be dropped onto any ship, truck, or dock (any framework or plain HTML page) because the interface (the platform's own APIs) is universal, rather than requiring a container built specifically to fit only one particular shipping company's fleet (a single framework's component model).

Key Concepts

1
Custom Elements let you define a new HTML tag (<my-widget>) backed by a JavaScript class extending HTMLElement, registered via customElements.define('my-widget', MyWidgetClass). The class can implement lifecycle callbacks — connectedCallback() (runs when the element is inserted into the document), disconnectedCallback() (runs on removal), and attributeChangedCallback() (runs when a watched attribute changes, provided the class defines a static observedAttributes array) — giving you hooks analogous to a framework component's mount/unmount/update lifecycle, but built directly into the platform.
<my-widget>HTMLElementcustomElements.define('my-widget', MyWidgetClass)connectedCallback()disconnectedCallback()
2
Shadow DOM provides genuine style and DOM encapsulation: attaching a shadow root to an element (element.attachShadow({ mode: 'open' })) creates a separate, isolated DOM subtree whose internal structure and CSS don't leak out to (or get affected by) the surrounding page's styles, and vice versa — solving a real, longstanding problem of CSS collisions between a reusable component and whatever page it's dropped into, without requiring CSS-in-JS or naming convention discipline (like BEM) to achieve the same isolation.
element.attachShadow({ mode: 'open' })
3
<template> elements hold inert, unrendered HTML markup that's parsed by the browser but not displayed or executed until explicitly cloned and inserted into the document via JavaScript — a native way to define reusable markup fragments without any framework's templating syntax. Together, these three APIs let you ship framework-agnostic, encapsulated components usable in any project regardless of what framework (or no framework) that project uses, at some cost in ergonomics compared to the more batteries-included component models frameworks provide.
<template>