Shadow DOM declarativo

Encapsulación creada desde el código HTML

Ahora que sabemos ¿Qué es el Shadow DOM? y que se utiliza para encapsular elementos en nuestro documento HTML, se nos podría plantear la siguiente duda: ¿Necesito Javascript para crear un Shadow DOM?

Generalmente, la respuesta a esta pregunta es sí, ya que hasta ahora era necesario realizar los pasos anteriores para crear un Shadow DOM en un elemento HTML. Por esta razón, el trabajo con Shadow DOM se reducía a aplicaciones web o documentos que trabajan en el cliente, es decir, en el navegador del usuario.

<app-element></app-element>

<script>
const element = document.querySelector("app-element");
element.attachShadow({ mode: "open" });
</script>

Sin embargo, con el Shadow DOM declarativo, podría ser posible hacerlo también desde el servidor, ya que permite crear Shadow DOM utilizando únicamente HTML.

Shadow DOM desde HTML

Mediante la propuesta de crear un Shadow DOM de forma declarativa, es decir, desde el HTML (sin necesidad de Javascript) se ha abierto un mundo de posibilidades muy interesantes, ya que a parte de simplificar su creación, permite incluso su generación desde la parte del servidor.

En esta modalidad, utilizaríamos la etiqueta HTML <template> con el atributo shadowroot indicando la modalidad del Shadow DOM, ya sea open o close, al igual que su análogo en Javascript:

<app-element>
<template shadowroot="open">
<style>
h2 { color: red }
::slotted(h2) { color: purple }
</style>
<h2>Shadow DOM</h2>
<slot></slot>
</template>
<h2>Light DOM</h2>
</app-element>

<h2>Global DOM</h2>

Observa que en este fragmento de código estamos utilizando la etiqueta <template>, sin embargo, está utilizando un atributo shadowroot para indicar el modo del Shadow DOM, que es lo que lo diferencia de otras etiquetas template normales.

En el caso de navegadores que soporten los Shadow DOM declarativos, esta etiqueta <template> se renderizará como un Shadow DOM resultando algo parecido a lo siguiente:

  • Shadow DOM en rojo, ya que se aplica el estilo del h2 desde dentro del Shadow DOM
  • Light DOM en lila, ya que se aplica el estilo del ::slotted() desde dentro del Shadow DOM
  • Global DOM en negro, ya que no se aplica ninguno de los anteriores, debido al Shadow DOM

En el caso de no soportarlo, sólo se vería el texto Light DOM y Global DOM, ambos en color negro.

Soporte en navegadores

Desgraciadamente, se trata de una característica experimental muy reciente y aún el soporte no está demasiado extendido. Por el momento, hay soporte en navegadores basados en Chromium 88+ o en las últimas versiones de Safari.

Si quieres ofrecer soporte a algún navegador que aún no soporte Declarative Shadow Root, puedes utilizar este pequeño fragmento de código Javascript, ejecutándolo al cargar una página. Esto buscará todas las etiquetas <template> con el atributo shadowroot y las eliminará creando una nueva con el Shadow DOM creado y adjuntado:

const dsr = document.querySelectorAll("template[shadowroot]");
dsr.forEach(template => {
const mode = template.getAttribute("shadowroot");
const shadowRoot = template.parentNode.attachShadow({ mode });
shadowRoot.appendChild(template.content);
template.remove();
});
Tabla de contenidos