HTML5 – DOM Shadow

Les bonnes pratiques de développement voudraient que l’on crée des composants encapsulés réutilisables, facilitant la maintenance. En HTML5, cette possibilité voit doucement le jour avec le DOM shadow qui est en cours de standardisation (supporté uniquement depuis la version 25 de Chrome, article testé avec Canary).

Le DOM shadow permet donc d’encapsuler du contenu en masquant le détails d’un composant, comme ses balises internes, ses styles css etc…

Pour implémenter un DOM shadow, nous devons créer un shadow root (le contenu du composant), qu’une fois créé, nous injecterons à un shadow host (le conteneur du composant).

Le shadow host :

<div id="myShadowHost">
   This text will be replaced.
</div>

Le shadow root :

var myHost = document.querySelector('#myShadowHost');
var myShadow = myHost.webkitCreateShadowRoot(); //createShadowRoot();
myShadow.innerHTML = '<b>This is the shadow root !</b>';

Ce qui affichera sur le navigateur :

domshadow1
Tandis que l’inspecteur de code lui ne verra que :

domshadow2

Il est également possible de créer des points d’insertion afin d’y garder le contenu du shadow host :

Le shadow host :

 <div id="myShadowHost2">
 <b>This is the shadow host text ! </b>
 </div>

Le shadow root :

var myHost2 = document.querySelector('#myShadowHost2');
 var myShadow2 = myHost2.webkitCreateShadowRoot(); //createShadowRoot();
 myShadow2.innerHTML = '<content></content> <br/>';
 myShadow2.innerHTML += 'And the shadow root here : <br/>';
 myShadow2.innerHTML += '<input type="text" name="login" placeholder="Enter your login"/> ';
 myShadow2.innerHTML += '<input type="submit" value="Send it !" />';

Ce qui une fois injecté s’affichera :

domshadow3

Pour completer ce nouveau composant, il est bien entendu possible d’ajouter des styles !
Par défaut, les styles définis à l’intérieur du Shadom DOM sont scopés au niveau de celui-ci et les styles communs à la page ne sont pas pas pris en compte à l’intérieur du Shadow DOM.

Exemple, ici les balises <i> seront en rouge :

<div id="myShadowHost2">
 <b>This is the shadow host text ! </b>
 </div>
<!-- -->
 <script type="text/javascript">
 var myHost2 = document.querySelector('#myShadowHost2');
 var myShadow2 = myHost2.webkitCreateShadowRoot(); //createShadowRoot();
 myShadow2.innerHTML = '<content></content> <br/>';
 myShadow2.innerHTML += '<style>i { color: red; }</style>'; //only for the host
 myShadow2.innerHTML += '<i>And the shadow root here ! </i><br/>';
</script>

domshadow4

Mais certaines propriétés sur l’élément shadow vont nous permettre de prendre le contrôle sur les styles globaux ou encore de “reset” les styles hérités.

myShadow2.innerHTML = “my content”;
//appliquer les styles globaux dans le shadow-root (false par défaut)
myShadow2.applyAuthorStyles = true;  
//reset les styles hérités au shadow root (false par défaut)
myShadow2.resetStyleInheritance = false;

Ajoutons donc le style de notre composant shadow host à notre feuille de style !

Le style :
 <style  type="text/css">
 /* Le style de l'élément host */
 .rooti{
 color: #3399FF;
 text-decoration: underline;
 }
 </style>
 <div id="myShadowHost2">
 <i>This text will not selected to content.</i>
 <b>This is the shadow host text ! </b>
 </div>
 <script type="text/javascript">
 var myHost2 = document.querySelector('#myShadowHost2');
 var myShadow2 = myHost2.webkitCreateShadowRoot(); //createShadowRoot();
 myShadow2.innerHTML = '<content select="b"></content> <br/>';
 myShadow2.innerHTML += '<i>And the shadow root here ! </i><br/>';
 myShadow2.applyAuthorStyles = true;
 myShadow2.resetStyleInheritance = false;
</script>

Pour un résultat de ce type :

domshadow5

Télécharger le code exemple (zip)

Pour plus d’informations :
http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-101/
http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/
http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-301/