# data[].attributes.body
Ya hemos visto que podemos usarlos para encapsular el uso de APIs de JavaScript externas como Google Maps y para extender el comportamiento de elementos nativos.
Otro uso es el de añadir marcado semántico o incluso contenido, por ejemplo, supongamos que para los productos de una tienda online tenemos el siguiente Web component:

<producto-tienda precio="99" precioAntes="88" href="/enlace-producto.html">
  <div class="nombre">Nombre producto</div>
  <div class="descripcion">Descripción producto</divglt;
</producto-tienda>

# data[].attributes.attachment_link.description
Getting this Sketch Library file dialed in. Responsive symbols for all the things.

# data[].attributes.body
Son un conjunto de características que actualmente están siendo añadidas por el W3C a las especificaciones HTML y DOM de forma que permite la creación de widgets o componentes reutilizables en documentos y aplicaciones web.

# data[].attributes.attachment_link.description
Discover & share this Web GIF with everyone you know. GIPHY is how you search, share, discover, and create GIFs.

# data[].attributes.body
Elementos personalizados - APIs para definir elementos HTML nuevos.

Sombra DOM - DOM y estilos encapsulados, con composición.

Importaciones de HTML - Métodos declarativos para importar documentos HTML a otros documentos.

Plantillas de HTML - El elemento <template> que permite que los documentos contengan trozos inertes del DOM.

# data[].attributes.body
Las plantillas HTML tienen soporte en Google Chrome, Mozilla Firefox, Edge de Microsoft, Safari, y Ópera.
La compatibilidad con la versión inicial de elementos personalizados y Shadow DOM, conocida como "v0", está presente en algunos navegadores basados en Blink como Google Chrome y Opera, y en Mozilla Firefox (requiere un cambio de configuración manual).

# data[].attributes.body
Hay varias librerías que están construidas sobre componentes web con el objetivo de aumentar el nivel de abstracción al crear elementos personalizados. Cuatro de las bibliotecas más importantes son: X-Tag, Slim.js, Polymer y Bosonic.

Dos de ellos, Bosonic y Polymer, proporcionan componentes listos para usar. Estos componentes se pueden utilizar indistintamente, ya que todos ellos están construidos con tecnologías web abiertas.​

# data[].attributes.attachment_link.readable_text
Out of the four specifications created for Web Components, the Shadow DOM is one of the most powerful. The Shadow DOM allows the component author to create an encapsulated sub-DOM tree for their component.

The latest version (V1) of the Shadow DOM specification introduces a new concept when creating a Shadow Root: the mode.

To create a Shadow Root for an element you call the attachShadow method providing an object as an argument which has a required mode property.

let $element = document.createElement("div");
$element.attachShadow({ mode: "open" }); // open or closed

I've not seen any articles discussing the practical difference between using open and closed mode of Shadow DOM so I thought I'd put a short article together along with some simple examples.

The Shadow DOM

Before I describe the difference between the open and closed modes it's import to understand what the Shadow DOM is and what it does.

As previously mentioned, the Shadow DOM allows a component author to create a sub-DOM tree. When creating a vanilla Web Component you'd typically do something like this:

classMyWebComponent extendsHTMLElement {
 constructor() {
 super();
 this.attachShadow({ mode: "open" });
 }
 connectedCallback() {
 this.shadowRoot.innerHTML = `
 <p>I'm in the Shadow Root!</p>
 `;
 }
}

window.customElements.define("my-web-component", MyWebComponent);

In the constructor we're using the attachShadow method to create an open Shadow Root for the Custom Element. We are then able to access the newly created shadow root via the shadowRoot property on the element instance. We can interact with the shadow root just like we would any DOM tree. For example we could use:

this.shadowRoot.querySelector("p");

To query for any paragraph elements in the shadow root.

We could also use appendChild to add a new element into the Shadow Root, or in the example above we are just using innerHTML to stamp an initial template.

If we add this Custom Element to a document and open Chrome Dev Tools, we'll get something like this:

We can see the element has an open Shadow Root with the paragraph element within. But what does this get us?

Because we have added the component template to a sub-DOM tree we get a certain level of encapsulation. If we added the following CSS to the main document head:

Because the paragraph element within our component is in the Shadow Root it won't inherit this style.

Additionally if we executed the following JavaScript on the main document object:

document.querySelector("p") // null

The result would be null because the Shadow Root won't be queried providing the desired encapsulation.

With these simple concepts component authors can create an encapsulated context for their component ensuring they have control over the style and can be confident that ambient JavaScript won't accidentally break their component.

The Shadow DOM has many more features to offer, if you'd like to learn more I'd recommend reading Shadow DOM v1: Self-Contained Web Components.

Open Mode

Now we are clear on how the Shadow DOM works in terms of its encapsulation we can move on to look at the differences between the open and closed modes.

The above example used the open mode which offers a decent level of encapsulation already, so what could closed mode possibility provide in addition? Not much actually.

When you create an open Shadow Root with this.attachShadow({ mode: "open" }) as we saw in the above examples you are then able to use the shadowRoot property to access the encapsulated sub-DOM tree.

In the example above we did this from within the Custom Element class definition in the connectedCallback. The shadowRoot is available on the element instance so we can just as easily access it externally from the main application.

const $myWebComponent = document.querySelector("my-web-component");
$myWebComponent.shadowRoot.querySelector("p").innerText = "Modified!";

Closed Mode

The closed mode of Shadow DOM is an interesting feature in that it is the cause of confusion for users while offering very little in return.

The closed mode of Shadow DOM provides the same encapsulation as the open mode but additionally allows the component author to hide access to the ShadowRoot, but not really - let me explain.

As we've just seen with open mode, once attachShadow has been called a reference to the elements shadow root is available on the shadowRoot property. This is not the case with closed mode: you'll find that attachShadow returns null.

let $element = document.createElement("div");
$element.attachShadow({ mode: "closed" });
$element.shadowRoot // null

So what does this mean for Web Components?

Because you can't use the shadowRoot property to access and manipulate the Shadow Root of the element you'll need to manually store a reference to the Shadow Root yourself.

class MyWebComponent extends HTMLElement {
 constructor() {
 super();
 this._root = this.attachShadow({ mode: "closed" });
 }
 connectedCallback() {
 this._root.innerHTML = `
 <p>I'm in the closed Shadow Root!</p>
 `;
 }
}

window.customElements.define("my-web-component", MyWebComponent);

The only difference here is that the component author has control over how the Shadow Root is exposed on the element:

const $myWebComponent = document.querySelector("my-web-component");
$myWebComponent.shadowRoot // null
$myWebComponent._root // shadow-root (closed)

This might be considered a benefit as in JavaScript, good developer etiquette dictates that a variable prefixed with an underscore "should be left well alone". But there is nothing really stopping anyone doing the following given the above example.

const $myWebComponent = document.querySelector("my-web-component");
$myWebComponent._root.querySelector("p").innerText = "Modified!";

Of course you could take it one step further and wrap the Custom Element definition in a closure to prevent the reference to the Shadow Root from being accessible:

(function(){
 const _shadows = new WeakMap();
 class MyWebComponent extends HTMLElement {
 constructor() {
 super();
 _shadows.set(this, this.attachShadow({ mode: "closed" }));
 }
 connectedCallback() {
 _shadows.get(this).innerHTML = `
 <p>I'm in the closed Shadow Root!</p>
 `;
 }
 }

 window.customElements.define("my-web-component", MyWebComponent);
})();

But really there is nothing stopping someone executing the following JavaScript before your component definition.

Element.prototype._attachShadow = Element.prototype.attachShadow;
Element.prototype.attachShadow = function() {
 return this._attachShadow( { mode: "open" } );
};

This will hijack the native attachShadow method and force every attachShadow call to always create an open Shadow Root - leaving your supposedly closed Shadow Root open for manipulation.

Conclusion

The closed mode of Shadow DOM has a single benefit which is to provide component authors with control over how the Shadow Root of their component is exposed (if at all) to the outside world.

Given that it's incredibly easy to work around paranoid component authors hiding their Shadow Roots its probably not worth the effort.

I'd be very interested to hear other developers views on this subject so please leave a comment or find me on Twitter @RevillWeb.

# data[].attributes.attachment_link.description
Out of the four specifications created for Web Components, the Shadow DOM is one of the most powerful. The Shadow DOM allows the component author to create an encapsulated sub-DOM tree for their component. The latest version (V1) of the Shadow DOM specification introduces a new concept when creating a Shadow Root: the mode.

# data[].attributes.body
Los componentes web fueron introducidos por Alex Russell en la conferencia Fronteers Conference de 2011.

Polymer, una biblioteca basada en componentes web, fue liberada por Google en 2013.

# data[].attributes.attachment_link.description
Discover & share this Web Design GIF with everyone you know. GIPHY is how you search, share, discover, and create GIFs.

# data[].attributes.body
La plantilla HTML es una forma de crear fragmentos de inserción de HTML que se usan a voluntad. La sintaxis de las plantillas HTML tiene este aspecto:

<html>
    <template>
        <p>The HTML you wish to instantiate on will</p>
    </template>
</html>

# data[].attributes.body
Hay dos tipos de elementos personalizados: autónomos e integrados. Los elementos personalizados autónomos son elementos HTML completamente diferenciados de los elementos HTML nativos, se construyen esencialmente desde abajo hacia arriba utilizando la API de elementos personalizados. Los elementos personalizados integrados son elementos que se construyen sobre elementos HTML nativos para reutilizar su funcionalidad.

# data[].attributes.body
Es una funcionalidad que permite al navegador web renderizar elementos DOM sin necesidad de insertarlos en el árbol principal DOM del documento.

# data[].attributes.body
La especificación de los Web Components empezó a desarrollarse hace aproximadamente un par de años, aunque algunas de las tecnologías que utiliza empezaron antes. Suponen una revolución en el mundo del desarrollo Web en términos de reutilización y encapsulación de código cliente, ya que permiten encapsular código HTML, CSS y JavaScript, de forma que no puede ser afectado por el código de la página que lo incluye.

# data[].attributes.body
HTML import es una herramienta para incluir documentos HTML y componentes web de fuentes externas sin necesidad de utilizar peticiones AJAX y métodos similares.

La sintaxis para hacer una importación HTML es la siguiente:

<link rel="import" href="mydocument.html">

# data[].attributes.attachment_link.description
Discover & share this Coding GIF with everyone you know. GIPHY is how you search, share, discover, and create GIFs.