Conceptly
← All Concepts
🧩

Web Components

ClientReusable, encapsulated UI components built without a framework

Web Components is a set of browser-native APIs that allow developers to create custom, reusable HTML elements with encapsulated styling and behavior -- without depending on any framework. It combines three independent standards: Custom Elements for defining new HTML tags, Shadow DOM for style and DOM isolation, and HTML Templates with Slots for reusable markup and content projection. Because they are built on web standards, Web Components work in any HTML environment where the browser supports them.

β–ΆArchitecture Diagram

πŸ” Structure

Dashed line animations indicate the flow direction of data or requests

Why do you need it?

Building web apps inevitably leads to recreating the same buttons, modals, and card layouts across multiple projects. Build a component in React and it cannot be used where React is not present; build it in Vue and it is locked to that ecosystem. Every time a framework changes or a new project starts, the same UI logic has to be rewritten. When multiple frameworks coexist on a single page, style collisions and event bubbling issues follow.

Why did this approach emerge?

When Google first introduced the Web Components idea through the Polymer project in 2011, it was motivated by the conviction that building components should be possible with browser standards alone, without needing a specific framework. In the early days, browser support was fragmented and polyfills were required, but between 2018 and 2020 all major browsers implemented Custom Elements v1 and Shadow DOM v1 as standards, bringing the technology to a practical stage. Today, lightweight helper libraries like Lit (Google) and FAST (Microsoft) reduce boilerplate, and Web Components are being used in practice for cross-framework shared components and embed widgets.

How does it work inside?

Web Components is a combination of three independent browser APIs. Custom Elements lets you create user-defined tags like <my-button> by extending HTMLElement and registering them with customElements.define(). Lifecycle hooks such as connectedCallback, disconnectedCallback, and attributeChangedCallback handle mounting, unmounting, and attribute changes. Shadow DOM creates an isolated DOM tree via this.attachShadow({ mode: 'open' }) that is separate from the outside. CSS inside does not leak out, and external CSS does not penetrate in. This isolation boundary enables embedding in third-party environments without style collisions. HTML Templates use the <template> tag to pre-parse DOM without rendering it to the screen. When needed, cloneNode(true) copies the template and inserts it into the Shadow DOM. The <slot> tag projects content provided by the component's consumer into specific positions inside the component.

Boundaries & Distinctions

Web Components and framework components like React or Vue share the goal of 'creating reusable UI pieces' but operate differently. React components run on top of the Virtual DOM and state management system and require the React runtime. Web Components are standard APIs that the browser understands natively, with no runtime dependency, and work in any HTML environment with just a `<my-component>` tag. On the other hand, state management and reactive updates are not part of the Web Components spec itself, so you must implement them yourself or use a helper like Lit. The potential collision between Shadow DOM and CSP (Content Security Policy) is also worth knowing. Using inline styles or scripts inside a Shadow DOM can be blocked by a CSP policy that lacks `unsafe-inline`. This particularly surfaces when using non-Constructable Stylesheets or when third-party widgets create `<style>` tags directly inside a Shadow Root. It is easy to assume Shadow DOM's style encapsulation makes CSP unnecessary, but the two mechanisms serve different roles and should be designed together. The distinction from Web Workers is also clear. Web Workers are an API for isolating computation on a background thread with no UI, while Web Components are an API for encapsulating UI at the DOM layer. They address different problems and have no overlapping use cases.

When should you use it?

Web Components truly shine when the same UI must be shared across multiple teams or multiple frameworks. If a company has an app built in React, an admin tool in Vue, and a static HTML marketing page -- all needing to use the same design system components -- a Web Components-based library is the only practically viable option. This is why large design systems like Google's Material Web Components, Adobe Spectrum, and FAST have taken this approach. The embed widget scenario is also a strong fit. Chat widgets, payment buttons, and social share buttons that are inserted into external sites must not collide with the host page's CSS. Shadow DOM isolation solves this problem at the browser level. However, for large SPAs where complex state management and fine-grained reactive rendering are central, trying to replace React or Vue entirely with Web Components alone will increase the development cost significantly. Web Components are the right fit for 'UI pieces that need to be shared'; for 'an entire app developed within a single framework', the framework's own component model is more suitable.

Design systems -- building a shared UI component library that is not tied to any specific frameworkMicro frontends -- coexisting app fragments built with different frameworks on a single pageLegacy integration -- introducing modern component patterns into existing HTML pages without React or VueThird-party widgets -- embed widgets that operate independently without style conflicts on external sites