What you'll learn
Web Components package native reusable UI through custom elements, Shadow DOM, templates, and slots. A strong component behaves like a well-designed built-in element.
By the end of this lesson, you'll be able to:
- Define a custom element
- Use lifecycle callbacks and Shadow DOM
- Design accessible attribute/property APIs
Core mental model
Use this decision table as a compact reference. Focus on what each tool means and when it earns its place in production code.
| Concept | What it means | Decision rule |
|---|---|---|
| Custom element | Registered HTML element class | Use for reusable platform-native UI boundaries |
| Shadow DOM | Encapsulated subtree and style scope | Use when encapsulation outweighs global styling needs |
| Slot | Consumer-provided content insertion point | Use to preserve semantic light-DOM content |
Professional workflow
Build the behavior in small, observable steps. Each step should leave something you can inspect or test.
- Describe the custom-element lifecycle boundary: inputs, outputs, state, timing, and expected failures.
- Implement the smallest correct path with names that expose intent.
- Add edge cases and failure handling before introducing abstractions.
- Verify behavior with realistic data and one deliberately adversarial example.
- Refactor only after the observable behavior is protected.
Make behavior observable
Guided code lab
Create a resilient status badge
The element reflects an attribute into an accessible internal label.
class StatusBadge extends HTMLElement {
static observedAttributes = ["status"];
connectedCallback() { this.render(); }
attributeChangedCallback() { this.render(); }
render() {
const status = this.getAttribute("status") ?? "unknown";
this.textContent = status;
this.setAttribute("role", "status");
}
}
customElements.define("status-badge", StatusBadge);Use template and slot
The host provides content; the component supplies layout and a named action area.
<template id="course-card-template">
<article>
<h2><slot name="title"></slot></h2>
<slot></slot>
<footer><slot name="action"></slot></footer>
</article>
</template>Production practice
Contract
Keep the custom-element lifecycle API explicit: accepted state, emitted events, DOM ownership, and cleanup.
Verification
Test with keyboard input, missing elements, repeated initialization, and teardown—not only a mouse happy path.
Operations
Measure user-visible latency and remove listeners, observers, object URLs, or media tracks when the feature ends.
Common failure mode
Independent workshop
Build a reusable course-progress custom element with a slot-based label and status event.
Your finished workshop must include:
- Documented attributes and properties
- Lifecycle-safe listeners
- Keyboard and screen-reader behavior
Definition of done
Recap & quick check
Key takeaways
- Custom elements define reusable tags
- Lifecycle callbacks own setup and cleanup
- Shadow DOM encapsulates
- Slots accept consumer content
Quick check
1. What must custom-element names contain?
2. Where should cleanup happen?
3. What does a slot receive?
Keep the workshop. Later modules deliberately build on these decisions, so each exercise can become part of your final portfolio architecture.