← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Web Components

frontend ES2018 Advanced

Also Known As

Custom Elements Shadow DOM HTML Templates

TL;DR

A suite of native browser APIs (Custom Elements, Shadow DOM, HTML Templates) for creating reusable, encapsulated HTML elements without frameworks.

Explanation

Web Components consist of three specs: Custom Elements (define new HTML tags with custom behaviour), Shadow DOM (encapsulated DOM subtree with scoped styles), and HTML Templates (<template> for inert markup). They work in all modern browsers without any build step or framework dependency. Shadow DOM provides true style encapsulation — styles inside do not leak out, styles outside do not leak in. Framework components (React, Vue) are built on similar concepts but require the framework to render.

Common Misconception

Web Components require a framework — they are native browser APIs that work in any HTML page without React, Vue, or Angular.

Why It Matters

Web Components enable truly reusable UI elements that work across frameworks — a custom <date-picker> works in a React app, a PHP-rendered page, or a plain HTML file.

Common Mistakes

  • Not calling super() in the Custom Element constructor — required before accessing 'this'.
  • Manipulating attributes before the element is connected to the DOM — use connectedCallback.
  • Not defining observed attributes with static get observedAttributes() — attributeChangedCallback never fires without it.
  • Forgetting that Shadow DOM style encapsulation blocks external CSS — use CSS custom properties for theming.

Code Examples

✗ Vulnerable
// Custom element without proper lifecycle:
class BadElement extends HTMLElement {
    constructor() {
        // Missing super() call
        this.innerHTML = '<p>Content</p>'; // DOM manipulation before connected
    }
}
✓ Fixed
class UserCard extends HTMLElement {
    static get observedAttributes() { return ['name', 'role']; }

    constructor() {
        super(); // Required
        const shadow = this.attachShadow({ mode: 'open' });
        shadow.innerHTML = `
            <style>:host { display: block; font-family: sans-serif; }</style>
            <div class="card"><slot name="name"></slot></div>
        `;
    }
    connectedCallback() { /* Element added to DOM */ }
    attributeChangedCallback(name, old, val) { /* Attribute changed */ }
}
customElements.define('user-card', UserCard);

Added 15 Mar 2026
Edited 22 Mar 2026
Views 20
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 3 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S
No pings yet today
Amazonbot 7 Google 4 Perplexity 2 Ahrefs 2 Unknown AI 2 ChatGPT 2
crawler 15 crawler_json 4
DEV INTEL Tools & Severity
🔵 Info ⚙ Fix effort: High
⚡ Quick Fix
Use Custom Elements to create reusable PHP-renderable HTML components — define once with customElements.define(), PHP renders <my-component> as plain HTML, JS upgrades it client-side
📦 Applies To
javascript ES2018 web
🔗 Prerequisites
🔍 Detection Hints
Complex jQuery widgets not reusable across PHP templates; framework component tied to specific JS framework when vanilla would work
Auto-detectable: ✗ No lighthouse chrome-devtools
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: File Tests: Update

✓ schema.org compliant