Web Components

Componentization is a fundamental principle in software development that involves breaking down a complex system into smaller, self-contained units called components. These components are designed to perform specific tasks, interact with each other in a well-defined manner, and can be reused in different contexts.

Component-based UI development has become the predominant approach in modern web application development.

Web Components are a set of standards that enable you to create reusable custom elements. They consist of 3 main technologies:

  • Custom Elements: Define your own HTML tags.
  • Shadow DOM: Encapsulate styles and markup, preventing style leakage.
  • HTML Templates: Define chunks of HTML that can be reused.

Defining a Custom Element

To create a custom element, you can extend the built-in HTMLElement class.

class MyElement extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' }); // Create a shadow root.
    const wrapper = document.createElement('div');
    wrapper.textContent = 'Hello, Web Component!';
    shadow.appendChild(wrapper);
  }
}

customElements.define('my-element', MyElement); // the hyphen is madactory.

Using the Custom Element

You can now use your custom element in HTML like any other element.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Web Components Demo</title>
  <script src="path/to/your-component.js" defer></script>
</head>
<body>
  <my-element></my-element>
</body>
</html>

Encapsulating Styles with Shadow DOM

The Shadow DOM allows you to style your custom elements without affecting the rest of the document.

class MyElement extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });
    
    const style = document.createElement('style');
    style.textContent = `
      div {
        color: white;
        background-color: blue;
        padding: 10px;
        border-radius: 5px;
      }
    `;

    const wrapper = document.createElement('div');
    wrapper.textContent = 'Styled Web Component!';
    
    shadow.appendChild(style);
    shadow.appendChild(wrapper);
  }
}

customElements.define('my-element', MyElement);

Using HTML Templates

You can define templates in your custom elements for reusable structures.

const template = document.createElement('template');
template.innerHTML = `
  <style>
    div {
      color: white;
      background-color: green;
      padding: 10px;
      border-radius: 5px;
    }
  </style>
  <div>Template-based Web Component!</div>
`;

class MyElement extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });
    shadow.appendChild(template.content.cloneNode(true));
  }
}

customElements.define('my-element', MyElement);

Why Web Components

Web Components provide a way to create reusable, encapsulated custom elements in your web applications. While many other frameworks and libraries offer similar capabilities—often with more elegant syntax or enhanced functionality—there's a significant advantage to using Web Components. Some of those frameworks may become obsolete in a few years, but Web Components are built on web standards, ensuring they are future-proof.

One of the most powerful aspects of Web Components is their ability to coexist with other frameworks and libraries. You can use them as a lower-level technique, allowing you to leverage the strengths of Web Components while still utilizing your preferred framework for higher-level application logic and UI management.