Web Components
45 minWeb Components are a suite of native web technologies that allow you to create reusable, encapsulated, custom HTML elements. They work in any framework or with no framework at all.
**Custom Elements**: The JavaScript API to define a new HTML tag (e.g., `<my-button>`). You extend `HTMLElement` and register it with `customElements.define()`.
**Shadow DOM**: Provides true encapsulation. Styles defined inside the Shadow DOM don't leak out, and global styles don't bleed in. It's like a mini-document inside your element.
**HTML Templates**: The `<template>` and `<slot>` tags allow you to define markup structures that aren't rendered until cloned, and to create flexible content projection (passing children into your component).
Key Concepts
- Custom Elements API.
- Shadow DOM & Encapsulation.
- HTML Templates & Slots.
- Lifecycle Callbacks (`connectedCallback`, etc.).
- Attribute Changed Callback.
Learning Objectives
Master
- Creating a standalone custom element
- Attaching and styling Shadow DOM
- Handling props via attributes
- Using slots for content projection
Develop
- Component-driven architecture
- Interoperability between frameworks
- Building a UI library
Tips
- Use `observedAttributes` and `attributeChangedCallback` to react to HTML attribute changes.
- Use CSS Variables (Custom Properties) to allow theming of your Shadow DOM components.
- Always call `super()` in the constructor.
- Use libraries like Lit to reduce the boilerplate of raw Web Components.
Common Pitfalls
- Forgetting to define the custom element name with a hyphen (e.g., `my-tag`, not `mytag`).
- Trying to style Shadow DOM elements from global CSS (won't work, except for inherited properties).
- Not handling cleanup in `disconnectedCallback` (memory leaks).
- Over-using Shadow DOM for simple elements where global styling is actually desired.
Summary
- Native, reusable UI components.
- Shadow DOM = True CSS isolation.
- Works everywhere (framework agnostic).
- The future of web UI libraries.
Exercise
Create a simple custom element using the Custom Elements API.
class MyGreeting extends HTMLElement {
connectedCallback() {
this.innerHTML = '<h2>Hello from a Web Component!</h2>';
}
}
customElements.define('my-greeting', MyGreeting);
// Usage: <my-greeting></my-greeting>
Exercise Tips
- Add observedAttributes and attributeChangedCallback to react to attribute changes.
- Use Shadow DOM for style isolation: this.attachShadow({ mode: 'open' });
- Add lifecycle callbacks: disconnectedCallback() for cleanup.
- Create a reusable component with props via attributes: <my-button label='Click me'></my-button>