DEV Community

Cover image for Web components
Vasilis Pavlou
Vasilis Pavlou

Posted on

Web components

What are web components

Web components are a set of web platform APIs and a specification for creating and using reusable custom HTML elements in web applications. They are designed to help developers encapsulate and package their UI elements and functionality, making it easier to build modular, maintainable, and reusable components for web applications.

Getting started with web components

  1. Custom Elements: Custom Elements allow developers to define their own HTML elements with custom behavior. These elements can encapsulate both the markup and the JavaScript logic needed for a specific component.
  2. Shadow DOM: Shadow DOM provides encapsulation for a web component's styles and markup. It allows you to create a separate DOM subtree with its own scoped CSS, preventing styles from leaking out and interfering with the rest of the page.
  3. HTML Templates: HTML Templates are a way to define reusable chunks of markup that can be instantiated in the DOM as needed. They are often used within custom elements to define the structure of the component.

Custom Elements:

  1. Custom Element Definition: Developers can define their own custom elements by creating a class that extends the HTMLElement base class or one of its derived classes. This class represents the custom element and defines its behavior and properties. For example:

    
    class MyCustomElement extends HTMLElement {
      constructor() {
        super();
        // Initialize your custom element here
      }
    }
    
    
  2. Custom Element Registration: After defining a custom element class, it needs to be registered with the browser using the customElements.define method. This associates the custom element's tag name with its JavaScript class:

    
    customElements.define('my-custom-element', MyCustomElement);
    
    

    Now, you can use <my-custom-element></my-custom-element> in your HTML, and it will be associated with your MyCustomElement class.

  3. Lifecycle Callbacks: Custom Elements provide lifecycle callbacks that allow you to define behavior at various points in the element's lifecycle. Some common lifecycle callbacks include:

    • constructor(): This is called when an instance of the custom element is created.
    • connectedCallback(): Invoked when the custom element is inserted into the DOM.
    • disconnectedCallback(): Called when the custom element is removed from the DOM.
    • attributeChangedCallback(): Triggered when specified attributes on the element change.

    You can use these callbacks to set up initial state, attach event listeners, and perform cleanup when necessary.

    Shadow DOM:

    Shadow DOM, short for Shadow Document Object Model, is a web platform feature that allows encapsulation of a part of a web component's HTML, CSS, and JavaScript. It enables developers to create isolated and self-contained DOM trees within an HTML document. Shadow DOM is particularly useful for building modular and reusable web components, ensuring that their internal structure and styles do not interfere with the rest of the page.

    Key characteristics of Shadow DOM include:

    1. Encapsulation: Shadow DOM encapsulates the markup, styles, and behavior of a web component, preventing them from affecting or being affected by the global page's DOM and CSS. This isolation helps avoid naming conflicts and unintended styling interactions.
    2. Scoped Styles: Styles defined within the Shadow DOM are scoped to the elements inside that Shadow DOM subtree. They do not leak out to affect other parts of the document and do not get affected by global page styles. This scoped styling helps maintain component integrity.
    3. Composition: Shadow DOM can be used to compose complex web components from smaller, encapsulated parts. These parts can be reused across different components and projects, promoting modularity and maintainability.
    4. JavaScript Encapsulation: In addition to encapsulating markup and styles, Shadow DOM also encapsulates JavaScript. JavaScript code running inside the Shadow DOM is isolated from the code outside, preventing potential conflicts and ensuring component integrity.

    Here's a simple example of creating a Shadow DOM within a custom element:

    class MyCustomElement extends HTMLElement {
      constructor() {
        super();
        const shadow = this.attachShadow({ mode: 'closed' });
        shadow.innerHTML = `
          <style>
            /* Scoped styles for this Shadow DOM */
            :host {
              color: blue;
            }
          </style>
          <p>This content is inside the Shadow DOM.</p>
        `;
      }
    }
    
    customElements.define('my-custom-element', MyCustomElement);
    
    

In this example, the attachShadow method is used with mode: 'closed', which hides the Shadow DOM from JavaScript outside of the MyCustomElement. The Shadow DOM still encapsulates the markup and styles, but it's not accessible or manipulable from external JavaScript.

HTML Templates and slots

HTML Templates, established with the <template> element, store reusable markup structures that are initially hidden and inert, awaiting dynamic insertion into the DOM, facilitating reusability.

Slots: Slots allow you to project content from the parent document into the named slots within the custom element. When using the custom element in the parent document, you can provide content for these slots:

To create a custom element with HTML templates and slots, you can use the <template> element and <slot> elements. Here's how you can modify your MyCustomElement class to use templates and slots:


class MyCustomElement extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'closed' });

    // Create a template element
    const template = document.createElement('template');
    template.innerHTML = `
      <style>
        /* Scoped styles for this Shadow DOM */
        :host {
          color: blue;
        }
      </style>
      <p>This content is inside the Shadow DOM.</p>
      <slot></slot> <!-- Define a slot for content -->
    `;

    // Clone the template content and append it to the shadow DOM
    const clone = document.importNode(template.content, true);
    shadow.appendChild(clone);
  }
}

customElements.define('my-custom-element', MyCustomElement);

Enter fullscreen mode Exit fullscreen mode

With this code, you create a <template> element that contains your component's structure, including a <slot> element for content. The <slot> element is a placeholder for where external content can be inserted when you use your custom element in HTML.

Here's an example of how you can use your custom element in HTML:


<my-custom-element>
  <p>Content inserted via slot.</p>
</my-custom-element>

Enter fullscreen mode Exit fullscreen mode

In this example, the content within the <my-custom-element> tag will replace the <slot> element's content inside the Shadow DOM.

Demo of a web component

You can find a working example of a web component here

Why aren’t web components more popular ?

Complexity: Web Components can be more verbose and require a deeper understanding of the web platform compared to using popular front-end frameworks. Some developers find the setup and usage of Web Components more complex and less straightforward, particularly when essential features like data-binding and state management are not readily available.

Limited Tooling and Ecosystem: Popular front-end frameworks like React and Vue have rich ecosystems with a vast collection of libraries, tools, and resources. Web Components, being a lower-level technology, do not have as mature or extensive an ecosystem, which can make development more challenging.

Reluctance to Adopt the Unknown: A transition from React, Angular, Vue, or Svelte to Web Components can be challenging due to the lack of widespread case studies or well-known products using Web Components. While more companies are now embracing Web Components to address their needs, there remains a demand for high-quality case studies and informative blog posts to facilitate this transition.

Top comments (0)