Como hemos dicho anteriormente, los WebComponents son un conjunto de características nativas que hacen posible la creación de componentes sin necesitar librerías o frameworks particulares, sino haciendo uso únicamente de tecnologías nativas como HTML, CSS y Javascript.
Cada una de estas características se puede usar de forma independiente, pero unidas, forman lo que se conoce habitualmente como WebComponents.
Custom Elements
Los custom elements (elementos HTML personalizados) son la característica estrella de los WebComponents. Con ellos, se nos permite crear nuestras propias etiquetas HTML, pudiendo dotarlas de su propia funcionalidad, marcado HTML o estilo CSS.
Observa el siguiente código HTML, donde aparece una etiqueta HTML <user-card>
, que realmente no existe dentro de las etiquetas HTML estándar:
<user-card name="ManzDev"></user-card>
Ahora imagina que ese código HTML, internamente, el navegador lo interpreta como el siguiente fragmento de código:
<div class="card">
<img src="manzdev.png" alt="ManzDev">
<h1>ManzDev</h1>
<p>ManzDev es un streamer de código.</p>
</div>
Justo eso es lo que hacen los custom elements
. Le indicamos al navegador que al leer esa etiqueta user-card
, debe interpretar en su lugar el fragmento de código HTML anterior. De esta forma, cada vez que escribamos <user-card>
sería como escribir todo el código anterior.
La forma rápida de diferenciar etiquetas personalizadas de las etiquetas nativas de HTML es observando que las primeras deben incluir en su nombre al menos un guión. Toda etiqueta HTML que tenga un guión en su nombre, es una etiqueta personalizada. La funcionalidad se implementará desde Javascript, como veremos más adelante.
► Leer más sobre Custom Elements
Templates
Otra característica interesante de WebComponents son los templates (plantillas). Se trata de una etiqueta nativa de HTML que nos permite crear contenido inerte en una página, esto es, contenido HTML que en principio no se procesará por el navegador, y que permanecerá «muerto» hasta que lo clonemos mediante Javascript.
<template id="user-template">
<div class="user">
<h1>Username</h1>
<img src="user-image.png" alt="Username">
<a href="https://website.com/">URL</a>
</div>
</template>
Todos los elementos que existen en el interior de la plantilla (imágenes, scripts, etc...) no serán procesados durante la carga de la página, por lo tanto, el navegador no invertirá recursos en su procesamiento. Esto nos puede interesar para preparar contenido reutilizable y que solo consuma recursos cuando lo clonemos desde Javascript.
► Leer más sobre Templates HTML
Shadow DOM
Probablemente, una de las características más interesantes (y complejas) de WebComponents sea el Shadow DOM. Esta característica opcional se basa en crear un marcado HTML (DOM, una estructura HTML) particular en un elemento HTML. De esta forma, además del DOM global del documento que normalmente utilizamos, tenemos uno particular en ese elemento.
Así pues, un elemento HTML con Shadow DOM se podría ver de esta forma:
<div class="element">
#shadow-root
<div class="inner-element">
...
</div>
</div>
El elemento .element
forma parte del DOM global del documento. Es un elemento vacío, sólo que en este ejemplo contiene un #shadow-root
, que es el DOM particular (Shadow DOM). En el interior de ese DOM particular existe una etiqueta .inner-element
. Dicha etiqueta HTML forma parte del Shadow DOM de .element
.
Aunque sirve para muchas cosas más, la misión del Shadow DOM es crear una estructura aislada. Es una excelente forma de crear estructuras con estilos CSS locales, que sólo afectan a su interior y no son afectados por el exterior, algo que los desarrolladores llevan buscando años de forma nativa.
Módulos ES (ESM)
Los módulos ECMAScript (ESModules o ESM) son otra de las características que hace posible que existan los WebComponents. Se trata de un estándar de Javascript que permite organizar elementos de nuestro código Javascript (constantes, funciones, clases, etc...) en módulos y exportarlos, para ponerlos a disposición de otro archivo Javascript que quiera importarlos.
Estos import
/export
se pueden hacer directamente desde Javascript a través de los Módulos ESM o incluso desde HTML, utilizando el atributo type
establecido al valor module
:
<script type="module" src="fichero.js"></script>
Este tipo de importación de módulos es equivalente al import "./fichero.js";
que podemos realizar desde Javascript y nos puede servir para cargar WebComponents directamente desde HTML.
En alguna ocasión es posible que nos encontremos una característica llamada Imports HTML. En algún momento llegó a formar parte de WebComponents, pero finalmente fue descartada y marcada como obsoleta, a favor de los Módulos ESM, una característica más moderna y potente.
HTML/JSON/CSS Modules
Los módulos ESM anteriormente mencionados, son la forma nativa de importar ficheros .js
desde Javascript o HTML. Sin embargo, sería genial poder hacer lo mismo con otro tipo de ficheros, como .json
, .css
o incluso .html
. Esa es la idea de JSON Modules, CSS Modules y HTML Modules.
Por ejemplo, observa la siguiente línea de código:
import songs from "./songs.json" with { type: "json" };
Esta sería la forma de importar, de forma estática un fichero JSON desde Javascript. Ten en cuenta que se añade una terminación with
mediante la cuál se le indica el tipo de dato importado, que en nuestro caso es un fichero .json
. De la misma forma, podríamos hacerlo con un import dinámico:
const songs = await import("songs.json", { with: { type: "json" } });
HTML Modules y CSS Modules (ojo, no confundir con CSS Modules) serán implementaciones nativas del navegador para permitir importar archivos HTML o CSS, al igual que el ejemplo de JSON anterior.
Estas especificaciones aún están en fase experimental, pero van soportándose poco a poco:
- JSON modules está soportado desde Chrome 91+
- CSS modules está soportado desde Chrome 93+
- HTML modules aún no está soportado en Chrome
Es posible que nos encontremos con una característica llamada Imports assertions. Antiguamente, esta característica se escribía como
assert
en lugar dewith
. Sin embargo,with
es la sintaxis definitiva.
CSS Scopes / Shadow Parts
Dentro del ecosistema de WebComponents, existen estrategias y mecánicas especializadas para tratar CSS en estos componentes.
Por un lado, tenemos los CSS Scopes, que surgen a raíz del CSS en los WebComponents. Con ellos podemos dar estilo a componentes que tengan un Shadow DOM:
- Pseudoclase
:host
- Pseudoclase funcional
:host()
- Pseudoclase funcional
:host-context()
- Pseudoelemento funcional
::slotted()
Por otro lado, tenemos las denominadas CSS Shadow Parts, una especificación que nos provee una forma de exponer zonas de un componente para poder darle estilo desde su exterior mediante el pseudoelemento ::part()
.