Etiquetas HTML personalizadas

Crear Custom Elements: Etiquetas HTML personalizadas

Los Custom Elements (Etiquetas HTML personalizadas) son una de las características que forman los WebComponents, y mediante los cuales podemos crear nuestras propias etiquetas HTML de forma nativa, dotándolos de su propio marcado, funcionalidad y/o estilo.

WebComponents: Bases de Custom Elements

Nombres de las etiquetas HTML

El estándar de HTML5 define que las etiquetas HTML oficiales deben estar formadas por una sola palabra, mientras que los custom elements (nuestras propias etiquetas HTML) deben estar formadas de al menos 2 palabras, separadas por un guión.

De esta forma, protegemos nuestras páginas o aplicaciones web para que, si en el futuro se añade una nueva etiqueta HTML estándar, no coincida con el mismo nombre que alguna nuestra.

Nombre de etiqueta ¿OK? Razón
<element> Una etiqueta sin - no puede ser un custom element.
<details> Idem. Además, <details> ya es un elemento HTML existente.
<app-component> ✔️ Correcto, cumple las condiciones para tener un buen nombre.
<AppComponent> No incluye -. Es la convención en ciertos frameworks JS, pero no en WebComponents.
<App-Component> Casi. Es correcto, pero las etiquetas HTML deberían ser siempre minúsculas.
<app-name-component> ✔️ Correcto, tiene al menos un -. Puedes añadir más si lo deseas.

Así pues, un custom element básico y sencillo, podría definirse de la siguiente forma:

<!-- Sencillo ejemplo de una etiqueta HTML propia (custom element) -->
<app-element></app-element>

<!-- Ejemplo incorrecto de custom element (no tiene guión) -->
<element></element>

Aprovechando la necesidad de utilizar dos palabras en un componente separadas por un guión, una buena práctica suele ser utilizar la primera palabra como «namespace» del componente. Es decir, utilizar el nombre de la funcionalidad, librería o aplicación, y así evitar posibles colisiones con otros elementos de terceros con nombre similar.

Crear un custom element

Antes de explicarlo, por aquí puedes ver como creo una etiqueta HTML personalizada:

Custom element básico

La forma más básica de crear una etiqueta personalizada HTML (custom element) es simplemente escribirla. El navegador la tratará como si fuera un elemento <span>.

<app-element>
Contenido de nuestro elemento personalizado
</app-element>

<style>
app-element {
background: black;
color: white;
padding: 5px;
}
</style>

Recuerda que también podemos darle estilo CSS al custom element, teniendo siempre en cuenta de que por defecto se trata de un elemento en línea, por lo que tenemos añadir un display diferente y darle unas dimensiones para observar cambios si no le hemos añadido contenido:

app-element {
display: block;
background: black;
color: white;
padding: 5px;
width: 125px;
height: 125px;
}

Pero respecto a todo el tema de los estilos CSS profundizaremos más adelante.

Centrémonos ahora en comprobar que, efectivamente, no nos estamos inventando nada. Vamos a localizar dos elementos HTML (uno definido correctamente y otro definido incorrectamente) y vamos a comprobar que tipo de elemento nos devuelve:

<app-element></app-element>
<element></element>

<script>
const appElement = document.querySelector("app-element");
const element = document.querySelector("element");

console.log("appElement: ", appElement, appElement.constructor.name); // HTMLElement
console.log("element: ", element, element.constructor.name); // HTMLUnkownElement
</script>

Lo único que estamos haciendo en las lineas anteriores es, localizando ambos custom elements y accediendo al nombre del constructor para saber en que tipo de elemento HTML está basado:

  • En el caso de <app-element> se trata efectivamente de un custom element, ya que está basado en HTMLElement, el tipo de dato base de cualquier etiqueta HTML.

  • En el caso de <element> nos dice que el tipo de dato es HTMLUnknownElement, ya que al no tener guión considera que es un elemento HTML oficial, pero el navegador desconoce de que elemento se trata (es desconocido).

Custom element extendido

Hasta ahora hemos creado un custom element sin funcionalidad. Básicamente, lo que hemos hecho hasta ahora ha sido crear un <span> con un nombre diferente, que no hace nada más que contener texto u otros elementos. Exactamente lo mismo que un <span>.

Los WebComponents se programan a través de una Clase Javascript, por lo que si no las conoces, deberías antes echar un vistazo al artículo Clases en Javascript (POO).

Vamos a dotar de funcionalidad nuestro Custom element. Para ello, haremos lo siguiente:

class AppElement extends HTMLElement {
constructor() {
super();
console.log("Inicializado...");
}
}

customElements.define("app-element", AppElement);

Hemos hecho dos cosas:

  1. En primer lugar, hemos definido una clase llamada AppElement. Observese que es una buena práctica utilizar PascalCase para nombrar la clase, en relación al nombre que le queremos dar al custom element. Dicha clase extiende de HTMLElement, una clase que es la base de cualquier elemento HTML, por lo que al heredarla nuestro custom element va a tener todas las características que tenga un elemento HTML estándar.

  2. En segundo lugar, hemos definido un constructor, que no es más que un método especial que se ejecuta cada vez que se crea una nueva instancia de clase, o en nuestro contexto, cada vez que alguien define o crea una etiqueta <app-element>. En nuestro ejemplo veremos que cada vez que creamos un elemento <app-element> nos aparece el texto del console.log() en la consola JS.

Ojo: Si defines un constructor en tu clase, no se te debe olvidar indicar el super() en el mismo, ya que es obligatorio llamar al constructor del padre si estás extendiendo de HTMLElement.

  1. En tercer y último lugar, no olvidar la última línea, donde llamamos a customElements.define() para indicar al navegador que existe una asociación entre el nombre de la etiqueta (primer parámetro) y la clase que implementa su funcionalidad (segundo parámetro). Profundizaremos más en esto en el siguiente artículo.

Con todo esto, y junto a métodos del DOM, podríamos comenzar a implementar funcionalidad dentro de la clase AppElement para dotar de características a nuestro custom element, como iremos viendo a lo largo de los siguientes capítulos.

// Nos devolverá que <app-element> es de tipo AppElement
const appElement = document.querySelector("app-element");
console.log("app-element: ", appElement, appElement.constructor.name);

Ahora, si intentamos hacer esta prueba, veremos que Javascript nos dice que <app-element> es de tipo AppElement, la clase que hemos extendido.

Soporte de Custom Elements

Actualmente, el soporte de custom elements en los navegadores es bastante bueno, ya que a excepción de algunas características menores en Safari, el soporte es pleno en navegadores actuales:

En el caso de querer dar soporte al extinto Internet Explorer, existe un polyfill oficial, denominado Custom Elements (v1) Polyfill que puede llegar a implementar las características más comunes en navegadores muy antiguos u obsoletos.

Tabla de contenidos