Custom Elements usando HTML Templates

Ahora que hemos visto en qué consisten las templates de HTML5, podemos ver cómo integrar una template y extraer su contenido, para incorporarla en un Custom Element.

En nuestra exploración de Web Components, hemos avanzado creando un Custom Element que nos permite mostrar notificaciones personalizables usando HTML templates. Este ejercicio nos ha servido para entender tanto el potencial como las limitaciones que enfrentamos cuando trabajamos con Custom Elements sin un aislamiento adecuado.

Para empezar, hemos definido un nuevo Custom Element llamado xnotificación. Es importante recordar que los nombres de los Custom Elements deben contener un guion para evitar conflictos con elementos HTML nativos, y es común usar un prefijo que identifique nuestra librería o proyecto. En nuestro caso, usamos la letra x como prefijo provisional.

El esqueleto básico del componente incluye el constructor, el método connectedCallback, el callback para cambios en atributos attributeChangedCallback y la propiedad estática observedAttributes para indicar qué atributos queremos observar. Así, podemos reaccionar cuando, por ejemplo, el atributo title cambie y actualizar el contenido de la notificación en consecuencia.

Para renderizar el contenido, reutilizamos la plantilla HTML que habíamos creado previamente. Usamos document.importNode para clonar el contenido del template y luego lo insertamos en el DOM del componente. Esto es eficiente porque al pasar un DocumentFragment a appendChild, el navegador inserta directamente los nodos hijos sin necesidad de iterar manualmente.

Sin embargo, al hacer esto nos encontramos con un problema fundamental: el contenido del template queda expuesto en el DOM principal de la página. Esto significa que los estilos y eventos definidos globalmente pueden afectar a nuestro componente, y viceversa. Por ejemplo, si en la página tenemos una clase CSS llamada .error que aplica cierto estilo, ese mismo estilo se aplicará dentro de nuestro componente si usamos esa clase en la plantilla. Esto rompe el aislamiento que esperamos de un componente reutilizable y modular.

Además, el código JavaScript externo puede manipular elementos internos del componente mediante selectores globales, lo que puede provocar comportamientos inesperados o errores difíciles de depurar. De igual forma, el código dentro del componente puede afectar elementos fuera de él, generando un acoplamiento indeseado.

Otro desafío que enfrentamos es la personalización del contenido. Aunque podemos crear atributos como title para modificar partes específicas del componente, esto se vuelve limitado cuando queremos incluir contenido más complejo, como etiquetas HTML dentro del texto o múltiples párrafos con formato. Los atributos HTML solo aceptan cadenas de texto, y escapar caracteres especiales o incluir etiquetas anidadas resulta complicado y poco práctico.

Por ejemplo, si queremos que el mensaje de error incluya una etiqueta <strong> para resaltar parte del texto, no podemos simplemente poner esa etiqueta dentro de un atributo sin que se interprete como texto plano. Esto limita la flexibilidad y expresividad de nuestros Custom Elements si solo usamos atributos para pasar contenido.

Todos estos problemas —la falta de aislamiento de estilos y eventos, y la dificultad para manejar contenido complejo— nos llevan a la necesidad de usar Shadow DOM. Esta API crea una barrera que aísla el DOM interno del componente del DOM principal de la página. Gracias a Shadow DOM, los estilos y eventos quedan encapsulados, evitando que el código externo afecte al componente y viceversa.

Shadow DOM actúa como un subárbol DOM separado, pero que sigue formando parte del documento, permitiendo que el navegador gestione el encapsulamiento de manera eficiente y transparente. Esto nos permite construir componentes verdaderamente reutilizables, modulares y protegidos de interferencias externas.

En definitiva, aunque hemos avanzado creando un Custom Element básico con atributos y plantillas, hemos visto que sin Shadow DOM enfrentamos problemas importantes de compartición de estilos y eventos. La introducción de Shadow DOM es el siguiente paso natural para construir componentes web robustos y aislados, y será el tema que abordaremos a continuación.

Lista de reproducción
  1. 1
    ¿Por qué existe la tecnología Web Components?
    13 minutos
  2. 2
    Tu primer Web Component
    19 minutos
  3. 3
    La etiqueta template de HTML5
    13 minutos
  4. 4
    ✱ Asterisco: Documentos DOM
    5 minutos
  5. 5
    Custom Elements usando HTML Templates
    9 minutos
  6. 6
    ✱ Asterisco: Microframeworks y JSX
    9 minutos
  7. 7
    Shadow DOM
    7 minutos
  8. 8
    Slots de Shadow DOM
    7 minutos
  9. 9
    ✱ Asterisco: Open vs Closed en Shadow DOM
    5 minutos
  10. 10
    Customized built-in elements
    14 minutos
  11. 11
    Polyfills para Web Components
    9 minutos
  12. 12
    ✱ Asterisco: The end... por el momento
    6 minutos
  13. 13
    ✱ Asterisco: Todo sigue igual (2020)
    6 minutos