DevHub Global Solutions | Educativo

Web Components: crea tus propias etiquetas HTML

Descubre cómo los Web Components permiten crear elementos HTML personalizados y reutilizables usando solo JavaScript, HTML y CSS. Esta tecnología nativa del navegador revoluciona el desarrollo frontend con componentes encapsulados y portables.
Web Components: crea tus propias etiquetas HTML
Diagrama mostrando la estructura de un Web Component con Shadow DOM

Fundamentos de la Tecnología

Los Web Components son un conjunto de estándares web que permiten crear elementos HTML personalizados con funcionalidad encapsulada. Se componen de tres tecnologías clave:

  • Custom Elements: Define nuevos elementos HTML
  • Shadow DOM: Proporciona encapsulación de estilos y estructura
  • HTML Templates: Permite crear fragmentos de markup reutilizables

Encapsulación

El Shadow DOM aísla estilos y DOM del documento principal

Reutilización

Componentes que funcionan en cualquier proyecto sin dependencias

Interoperabilidad

Funcionan con React, Vue, Angular y otros frameworks

// Registrar un nuevo elemento
class MiComponente extends HTMLElement {
  constructor() {
    super();
    // Crear Shadow DOM
    this.attachShadow({mode: 'open'});
    this.shadowRoot.innerHTML = `
      <style>
        :host { display: block; }
        p { color: #2c3e50; }
      </style>
      <p>¡Hola desde mi componente!</p>
    `;
  }
}

customElements.define('mi-componente', MiComponente);

Los Web Components son compatibles con todos los navegadores modernos sin necesidad de polyfills

Tecnología Función Estado
Custom Elements Definir nuevos elementos Estándar
Shadow DOM Encapsulación Estándar
HTML Templates Markup reutilizable Estándar
HTML Imports Carga de componentes Obsoleto

Creando tu Primer Componente

Vamos a construir un botón personalizado con estado:

  1. Extiende la clase HTMLElement
  2. Usa el Shadow DOM para encapsulación
  3. Gestiona propiedades con observedAttributes
  4. Define métodos del ciclo de vida
class MiBoton extends HTMLElement {
  static get observedAttributes() {
    return ['disabled'];
  }
  
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
    this.shadowRoot.innerHTML = `
      <button>
        <slot></slot>
      </button>
      <style>
        button {
          padding: 12px 24px;
          background: #4285f4;
          color: white;
          border: none;
          border-radius: 4px;
          cursor: pointer;
        }
        button:disabled { opacity: 0.5; }
      </style>
    `;
    this.button = this.shadowRoot.querySelector('button');
  }
  
  connectedCallback() {
    this.button.addEventListener('click', this._onClick);
  }
  
  disconnectedCallback() {
    this.button.removeEventListener('click', this._onClick);
  }
  
  attributeChangedCallback(name, oldVal, newVal) {
    if(name === 'disabled') {
      this.button.disabled = newVal !== null;
    }
  }
  
  _onClick = () => {
    this.dispatchEvent(new CustomEvent('boton-click', {
      bubbles: true,
      composed: true
    }));
  }
}

customElements.define('mi-boton', MiBoton);

Usa el componente en tu HTML: <mi-boton>Click Aquí</mi-boton>

Comunicación entre Componentes

Los componentes pueden comunicarse mediante:

  • Atributos y propiedades
  • Eventos personalizados
  • Patrón de publicación/suscripción
  • API de contexto (experimental)
// Disparar evento personalizado
this.dispatchEvent(new CustomEvent('actualizacion-datos', {
  detail: { usuario: 'Juan', rol: 'admin' },
  bubbles: true,
  composed: true
}));

// Escuchar evento
document.addEventListener('actualizacion-datos', (e) => {
  console.log('Datos recibidos:', e.detail);
});

Mejores Prácticas

Consejos para desarrollar componentes robustos:

Nomenclatura

Usa guión en nombres (ej: mi-componente) para diferenciar de elementos nativos

Encapsulación

Utiliza Shadow DOM para evitar conflictos de CSS

Accesibilidad

Implementa roles ARIA y propiedades accesibles

Rendimiento

Usa connectedCallback para inicialización diferida

Caso Solución
Props complejas Usar propiedades en lugar de atributos
Temas personalizados Variables CSS y ::part
Renderizado dinámico Slot elements y <template>
Pruebas Web Test Runner o Jest

Ecosistema y Herramientas

Bibliotecas que mejoran la experiencia con Web Components:

// Ejemplo con Lit
import { LitElement, html, css } from 'lit';

class LitButton extends LitElement {
  static styles = css`
    button { /* estilos */ }
  `;
  
  render() {
    return html`<button><slot></slot></button>`;
  }
}

customElements.define('lit-button', LitButton);

Lit, Stencil y FAST amplían capacidades manteniendo estándares

CF

Sobre el autor

Desarrollador Frontend Senior con 10 años de experiencia. Especialista en arquitecturas de componentes y estándares web. Autor de 'Componentes Reutilizables en la Web Moderna'.