πŸ› Web Components: What they are, What they're for, and How they can simplify your frontend projects

  

In modern frontend development, the need to create modular, reusable and interoperable interfaces is increasingly strong. In this context, Web Components are proposed as a standard, powerful and framework-agnostic solution to address issues of encapsulation, duplication and maintenance of UI code.

In this article we will see:

  • What are Web Components and how do they work
  • Why are they useful in real scenarios
  • A concrete use case adopted by GitHub
  • A complete practical example with code and architectural benefits
πŸ”— Do you like Techelopment? Check out the site for all the details!

πŸ” What are Web Components?

Web Components are a browser-native technology that allows you to create custom, encapsulated and reusable HTML components, without depending on external frameworks.

They are based on four fundamental specifications:

  1. Custom Elements – Definition of new HTML tags via JavaScript (customElements.define()).
  2. Shadow DOM – Encapsulation of style and markup to avoid conflicts with the rest of the page.
  3. HTML Templates – Reusable HTML templates that do not render until used.
  4. ES Modules – JavaScript module support for organizing and importing code.

Basic example:

class MyButton extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' }).innerHTML = `
            <style>
                button { background: teal; color: white; padding: 10px; border: none; border-radius: 4px; } 
            </style> 
            <button><slot></slot></button> 
        `; 
    }
}
customElements.define('my-button', MyButton);

Usage:

<my-button>Click here</my-button>

🎯 Why use them: advantages and problems solved

Problem Solution offered by Web Components
Style and JavaScript conflicts Shadow DOM for complete isolation
Code duplication in multiple projects Components reusable everywhere
Framework lock-in Native and agnostic web standards
Hard integration in microfrontend architectures Interoperable components

Web Components are ideal for:

  • Cross-framework design systems
  • Legacy applications
  • Distributed microfrontends and widgets
  • Shared development between different teams

🏒 Real case: GitHub and Web Components

GitHub has adopted Web Components to improve the modularity and scalability of the UI. Real-world examples include:

  • <relative-time> to show relative dates
  • <markdown-toolbar> for the text editor
  • <details-dialog> for modal windows

Motivation:

  • Modular code management
in an existing monolith
  • Compatibility across teams and environments
  • Simplified component maintenance
  • Apple, Adobe, and Salesforce also use Web Components to create scalable design systems and components cross-app.


    πŸ§ͺ Practical Example: Reusable Feedback Widget

    🎯 Requirement

    In an organization with multiple apps (React, Angular, Vanilla JS), you need a uniform component to collect user feedback:

    • Compact and consistent interface
    • Asynchronous dispatch to an endpoint
    • No style conflicts
    • Easy integration into all environments

    πŸ› ️ Implementation with Web Component

    File structure:

    feedback-widget/
    ├── feedback-widget.js
    └── index.html

    Code feedback-widget.js:

    class FeedbackWidget extends HTMLElement { 
        constructor() { 
        super(); 
        this.attachShadow({ mode: 'open' }); 
    
        this.shadowRoot.innerHTML = ` 
            <style> 
                * { font-family: sans-serif; } 
                .widget { border: 1px solid #ccc; padding: 12px; border-radius: 8px; background: #f9f9f9; width: 250px; } 
                textarea, select, button { width: 100%; margin-top: 8px; } 
                .success { color: green; display: none; margin-top: 8px; } 
            </style> 
            <div class="widget"> 
            <label for="rating">Rating:</label> 
            <select id="rating"> 
                <option value="">--</option> 
                <option value="1">1 - Very bad</option> 
                <option value="5">5 - Excellent</option> 
            </select> 
            <textarea id="comment" placeholder="Write a comment..."></textarea> 
            <button id="submit">Send Feedback</button> 
            <div class="success">Thanks for the feedback!</div> 
            </div> 
        `; 
    } 
    
    connectedCallback() { 
        const rating = this.shadowRoot.getElementById('rating'); 
        const comment = this.shadowRoot.getElementById('comment'); 
        const button = this.shadowRoot.getElementById('submit'); 
        const success = this.shadowRoot.querySelector('.success'); 
    
        button.addEventListener('click', async () => { 
            const payload = { 
                rating: rating.value, 
                comment: comment.value, 
            }; 
    
            await fetch('https://example.com/api/feedback', { 
                method: 'POST', 
                body: JSON.stringify(payload), 
                headers: { 'Content-Type': 'application/json' }, 
            }); 
    
            success.style.display = 'block'; 
                button.disabled = true; 
            }); 
        }
    }
    customElements.define('feedback-widget', FeedbackWidget);

    HTML demo index.html:

    <!DOCTYPE html>
    <html lang="en">
        <head> 
            <script type="module" src="./feedback-widget.js"></script>
        </head>
        <body>
            <h2>Portal Feedback</h2>
            <feedback-widget></feedback-widget>
        </body>
    </html>

    ✅ Benefits achieved

    Objective Result with Web Component
    Standard UI in all apps ✅ Centralized style and structure
    Easy integration ✅ Native HTML tag
    Logic/style encapsulation ✅ Shadow DOM
    No framework dependencies ✅ Works everywhere
    Maintenance and versioning ✅ Distributable via CDN/NPM

    πŸ“ˆ Possible extensions

    • Dynamic theme: <feedback-widget theme="dark">

    • Custom events: this.dispatchEvent(new CustomEvent('submitted'))

    • Configurability via attributes (endpoint, lang)

    • Test: unitary with Jest, e2e with Playwright

    • Deployment: via CDN (Skypack, jsDelivr) or npm


    πŸ“’ NOTE: What is connectedCallback()?

    It is a lifecycle method that is automatically called by the browser when a Web Component is inserted into the DOM (document HTML).

    πŸ“Œ What is it for?

    It is used to execute initialization code, such as:

    • add event listeners,
    • fetch data,
    • update the interface,
    • initialize logic that requires the component to actually be "active" on the page.

    πŸ“˜ Basic syntax

    class MyElement extends HTMLElement {
        connectedCallback() {
            console.log('The component has been added to the DOM!');
        }
    }
    customElements.define('my-element', MyElement);

    πŸ” When is it called?

    • ✅ As soon as the component is inserted into the DOM, even if dynamically
    • ❌ It is not called until the element is created in JS but not yet added to the DOM

    🧠 Practical example

    class HelloWorld extends HTMLElement {
        connectedCallback() {
            this.innerHTML = `<p>Hello from the Web Component!</p>`;
        }
    }
    customElements.define('hello-world', HelloWorld);

    In the DOM:

    <hello-world></hello-world>

    πŸ” When the browser "sees" <hello-world>, it calls connectedCallback() and replaces the content with the defined one.

    🧹 Note: there are also other useful methods

    Method When called
    connectedCallback() When the element enters the DOM
    disconnectedCallback() When removed from the DOM
    attributeChangedCallback() When observed attributes change
    adoptedCallback() When moved between documents (e.g. iframe)

    🧩 Conclusion

    Web Components are a robust, standard and interoperable alternative for building modern UIs. They offer:

    • Perfect isolation of style and logic
    • Reuse between frameworks and apps
    • Easy integration into microfrontends or legacy portals
    • Centralized maintenance and testing

    If your team works in mixed environments or on enterprise projects, Web Components can make the difference between a fragile design system and a scalable, robust and modern one.



    Follow me #techelopment

    Official site: www.techelopment.it
    facebook: Techelopment
    instagram: @techelopment
    X: techelopment
    Bluesky: @techelopment
    telegram: @techelopment_channel
    whatsapp: Techelopment
    youtube: @techelopment