aboutsummaryrefslogtreecommitdiff
path: root/files/fr/web/web_components/using_templates_and_slots/index.html
blob: 860628ec067005e6efba4601fbcd2186303afc3e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
---
title: Utiliser les éléments template et slot
slug: Web/Web_Components/Using_templates_and_slots
translation_of: Web/Web_Components/Using_templates_and_slots
original_slug: Web/Web_Components/Utilisation_des_templates_et_des_slots
---
<div>{{DefaultAPISidebar("Web Components")}}</div>

<p>Cet article explique comment utiliser les éléments <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a> et <a href="/fr/docs/Web/HTML/Element/slot"><code>&lt;slot&gt;</code></a> pour créer un modèle (<i lang="en">template</i>) flexible qui peut ensuite être utilisé pour alimenter le Shadow DOM d'un composant web.</p>

<h2 id="la_vérité_sur_les_modèles">La vérité sur les modèmes</h2>

<p>Lorsqu'une structure de balises se répète sur une page web, il est judicieux d'utiliser un modèle plutôt que d'écrire cette même structure encore et encore. Il était déjà possible de le faire, mais l'élément HTML <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a> (pris en charge par les navigateurs modernes) nous facilite la tâche. Cet élément et ce qu'il renferme n'est pas directement retranscrit dans le DOM, mais peut par contre toujours être manipulé avec JavaScript.</p>

<p>Voyons un exemple simple&nbsp;:</p>

<pre class="brush: html">
&lt;template id="my-paragraph"&gt;
  &lt;p&gt;My paragraph&lt;/p&gt;
&lt;/template&gt;
</pre>

<p>Ceci restera invisible sur la page tant qu'aucune référence n'y sera faite dans le code JavaScript puis ajouté au DOM, en utilisant par exemple&nbsp;:</p>

<pre class="brush: js">
let template = document.getElementById('my-paragraph');
let templateContent = template.content;
document.body.appendChild(templateContent);
</pre>

<p>Quoique trivial, cet exemple vous permet d'entrevoir l'interêt d'utiliser des modèles.</p>

<h2 id="accorder_modèles_et_composants_web">Accorder modèles et composants web</h2>

<p>Les modèles sont utiles en eux-mêmes, mais ils fonctionnent encore mieux avec des composants web. Créons un composant web qui utilise notre modèle comme contenu de son Shadow DOM. Nous l'appellerons <code>&lt;my-paragraph&gt;</code>&nbsp;:</p>

<pre class="brush: js">
customElements.define('my-paragraph',
  class extends HTMLElement {
    constructor() {
      super();
      let template = document.getElementById('my-paragraph');
      let templateContent = template.content;

      const shadowRoot = this.attachShadow({mode: 'open'})
        .appendChild(templateContent.cloneNode(true));
  }
})</pre>

<p>Le point important à noter est que l'on ajoute un clone du contenu du modèle à la racine du DOM, créé à l'aide de la méthode <a href="/fr/docs/Web/API/Node/cloneNode"><code>Node.cloneNode()</code></a>.</p>

<p>Et parce que nous ajoutons son contenu à un Shadow DOM, on peut inclure des informations de mise en forme à l'intérieur de l'élément <code>&lt;template&gt;</code> dans d'un élément <a href="/fr/docs/Web/HTML/Element/style"><code>&lt;style&gt;</code></a>, qui est ensuite encapsulé à l'intérieur de l'élément personnalisé. Cette procédure n'aurait pas fonctionné si on avait ajouté le contenu à un DOM standard.</p>

<p>Par exemple&nbsp;:</p>

<pre class="brush: html">
&lt;template id="my-paragraph"&gt;
  &lt;style&gt;
    p {
      color: white;
      background-color: #666;
      padding: 5px;
    }
  &lt;/style&gt;
  &lt;p&gt;My paragraph&lt;/p&gt;
&lt;/template&gt;
</pre>

<p>On peut maintenent utiliser le modèle dans le document HTML:</p>

<pre class="brush: html">
&lt;my-paragraph&gt;&lt;/my-paragraph&gt;
</pre>

<div class="note">
<p><strong>Note :</strong> Les modèles sont bien pris en charge par les navigateurs&nbsp;; l'API Shadow DOM est pris en charge par défaut dans Firefox (à partir de la version 63), Chrome, Opera, Safari et Edge (à partir de la version 70).</p>
</div>

<h2 id="plus_de_flexibilité_avec_les_slots">Plus de flexibilité avec les slots</h2>

<p>Jusque-là, nous avons vu une première utilisation de l'élément <code>&lt;template&gt;</code>. Cette implémentation n'est pas très flexible&nbsp;; elle ne permet d'afficher que du texte, c'est-à-dire qu'il est aussi utile qu'un paragraphe classique&nbsp;! Il est possible d'insérer du texte dans chaque instance d'élément de façon déclarative grâce à <a href="/fr/docs/Web/HTML/Element/slot"><code>&lt;slot&gt;</code></a>. Cette fonction est moins bien prise en charge que <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a>, disponible sur Chrome 53, Opera 40, Safari 10, Firefox 59 et Edge 79.</p>

<p>Les emplacements (<i lang="en">slots</i>) sont identifiés par leur attribut <code>name</code>, et permettent de définir des emplacements dans le modèle qui peuvent être alimentés avec n'importe quelle structure HTML.</p>

<p>Donc, si on souhaite ajouter un emplacement dans le précédent exemple, on peut modifier l'élément de cette façon&nbsp;:</p>

<pre class="brush: html">
&lt;p&gt;&lt;slot name="my-text"&gt;Texte par défaut&lt;/slot&gt;&lt;/p&gt;
</pre>

<p>Si le contenu de l'emplacement n'est pas défini quand l'élément est inclus dans la page, ou si les emplacements ne sont pas pris en charge par le navigateur, <code>&lt;my-paragraph&gt;</code> contiendra simplement le texte statique précisé dans le modèle.</p>

<p>Pour définir le contenu de l'emplacement, on insère une structure HTML dans <code>&lt;my-paragraph&gt;</code> avec un attribut <a href="/fr/docs/Web/HTML/Global_attributes#slot"><code>slot</code></a> dont la valeur est égale au nom de l'emplacement que l'on veut alimenter. Comme précédemment, on peut utiliser n'importe quelle structure HTML, par exemple&nbsp;:</p>

<pre class="brush: html">
&lt;my-paragraph&gt;
  &lt;span slot="my-text"&gt;Voici un autre texte&amp;nbsp;!&lt;/span&gt;
&lt;/my-paragraph&gt;
</pre>

<p>ou</p>

<pre class="brush: html">
&lt;my-paragraph&gt;
  &lt;ul slot="my-text"&gt;
    &lt;li&gt;Voici un autre texte&amp;nbsp;!&lt;/li&gt;
    &lt;li&gt;dans une liste!&lt;/li&gt;
  &lt;/ul&gt;
&lt;/my-paragraph&gt;
</pre>

<div class="notecard note">
  <p><strong>Note&nbsp;:</strong> Un élément <a href="/fr/docs/Web/HTML/Element/slot"><code>&lt;slot&gt;</code></a> sans nom sera rempli avec l'ensemble des nœuds-fils de plus haut niveau de l'élément personnalisé qui n'ont pas d'attribut <a href="/fr/docs/Web/HTML/Global_attributes#slot"><code>slot</code></a>. Cela inclut les nœuds texte.</p>
</div>

<p>Et c'est tout pour ce premier exemple. Si vous souhaitez manipuler les emplacements, vous pouvez <a href="https://github.com/mdn/web-components-examples/tree/master/simple-template">voir la page sur GitHub</a> (voir aussi <a href="https://mdn.github.io/web-components-examples/simple-template/">le résultat</a>).</p>

<h2 id="un_exemple_plus_complexe">Un exemple plus complexe</h2>

<p>Pour finir, voyons un exemple un peu moins trivial.</p>

<p>L'ensemble de fragments de code qui suit illustre comment utiliser <a href="/fr/docs/Web/HTML/Element/slot"><code>&lt;slot&gt;</code></a> avec <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a> et un peu de JavaScript afin de&nbsp;:</p>

<ul>
	<li>Créer un élément <strong><code>&lt;element-details&gt;</code></strong> avec des <a href="/fr/docs/Web/HTML/Element/slot#named-slot">emplacements nommés</a> à <a href="/fr/docs/Web/API/ShadowRoot">la racine virtuelle (<code>ShadowRoot</code>)</a></li>
	<li>Concevoir l'élément <strong><code>&lt;element-details&gt;</code></strong> afin que, lorsqu'il est utilisé dans les documents, il soit rendu en composant le contenu de l'élément avec le contenu de <a href="/fr/docs/Web/API/ShadowRoot">la racine virtuelle</a>. Autrement dit, les parties du contenu de l'élément seront utilisées afin de remplir <a href="/fr/docs/Web/HTML/Element/slot#named-slot">les emplacements nommés</a> dans sa <a href="/fr/docs/Web/API/ShadowRoot">racine virtuelle</a></li>
</ul>

<p>Il est techniquement possible d'utiliser un élément <a href="/fr/docs/Web/HTML/Element/slot"><code>&lt;slot&gt;</code></a> sans élément <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a> (par exemple au sein d'un <a href="/fr/docs/Web/HTML/Element/div"><code>&lt;div&gt;</code></a> classique) tout en tirant parti des fonctionnalités d'emplacement fournies par <a href="/fr/docs/Web/HTML/Element/slot"><code>&lt;slot&gt;</code></a> pour le contenu du Shadow DOM. On peut ainsi éviter d'avoir à d'abord accéder à la propriété <code>content</code> du modèle (et de la cloner). Toutefois, il est souvent plus pratique d'ajouter des emplacements au sein d'un élément <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a>, car il est peu probable de définir un composant à partir d'un élément déjà rendu.</p>

<p>De plus, même si l'élément n'est pas déjà rendu, le rôle de conteneur porté par le modèle sera sémantiquement plus clair en utilisant <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a>. De plus, <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a> peut avoir des éléments qui lui sont directement rattachés comme <a href="/fr/docs/Web/HTML/Element/td"><code>&lt;td&gt;</code></a>. Ce même élément disparaîtrait s'il était ajouté à un élément <a href="/fr/docs/Web/HTML/Element/div"><code>&lt;div&gt;</code></a>.</p>

<div class="note">
<p><strong>Note :</strong> Vous pourrez retrouver l'exemple complet sur <a href="https://github.com/mdn/web-components-examples/tree/master/element-details">le dépôt GitHub pour element-details</a> (voir également <a href="https://mdn.github.io/web-components-examples/element-details/">le résultat en action</a>).</p>
</div>

<h3 id="créer_un_modèle_avec_des_emplacements">Créer un modèle avec des emplacements</h3>

<p>Tout d'abord, on utilise l'élément <a href="/fr/docs/Web/HTML/Element/slot"><code>&lt;slot&gt;</code></a> au sein d'un élément <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a> afin de créer notre nouveau <a href="/fr/docs/Web/API/DocumentFragment">fragment de document</a> "element-details-template" qui contient quelques <a href="/fr/docs/Web/HTML/Element/slot#named-slot">emplacements nommés</a>&nbsp;:</p>

<pre class="brush: html">
&lt;template id="element-details-template"&gt;
  &lt;style&gt;
  details {font-family: "Open Sans Light",Helvetica,Arial}
  .name {font-weight: bold; color: #217ac0; font-size: 120%}
  h4 { margin: 10px 0 -8px 0; }
  h4 span { background: #217ac0; padding: 2px 6px 2px 6px }
  h4 span { border: 1px solid #cee9f9; border-radius: 4px }
  h4 span { color: white }
  .attributes { margin-left: 22px; font-size: 90% }
  .attributes p { margin-left: 16px; font-style: italic }
  &lt;/style&gt;
  &lt;details&gt;
    &lt;summary&gt;
      &lt;span&gt;
        &lt;code class="name"&gt;&amp;lt;&lt;slot name="element-name"&gt;BESOIN D'UN NOM&lt;/slot&gt;&amp;gt;&lt;/code&gt;
        &lt;i class="desc"&gt;&lt;slot name="description"&gt;BESOIN D'UNE DESCRIPTION&lt;/slot&gt;&lt;/i&gt;
      &lt;/span&gt;
    &lt;/summary&gt;
    &lt;div class="attributes"&gt;
      &lt;h4&gt;&lt;span&gt;Attributs&lt;/span&gt;&lt;/h4&gt;
      &lt;slot name="attributes"&gt;&lt;p&gt;Aucun&lt;/p&gt;&lt;/slot&gt;
    &lt;/div&gt;
  &lt;/details&gt;
  &lt;hr&gt;
&lt;/template&gt;
</pre>

<p>Voyons les caractéristiques de cet élément <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a>&nbsp;:</p>

<ul>
	<li>Ce <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a> contient un élément <a href="/fr/docs/Web/HTML/Element/style"><code>&lt;style&gt;</code></a> avec un ensemble de règles CSS dont la portée est celle du fragment de document créé par l'élément <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a>.</li>
	<li>Ce <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a> utilise un élément <a href="/fr/docs/Web/HTML/Element/slot"><code>&lt;slot&gt;</code></a> et l'attribut <a href="/fr/docs/Web/HTML/Element/slot#attr-name"><code>name</code></a> correspondant afin d'avoir trois <a href="/fr/docs/Web/HTML/Element/slot#named-slot">emplacements nommés</a>&nbsp;:
	<ul>
		<li><code>&lt;slot name="element-name"&gt;</code></li>
		<li><code>&lt;slot name="description"&gt;</code></li>
		<li><code>&lt;slot name="attributes"&gt;</code></li>
	</ul>
	</li>
	<li>L'élément <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a> intègre les <a href="/fr/docs/Web/HTML/Element/slot#named-slot">emplacements nommés slots</a> dans un élément <a href="/fr/docs/Web/HTML/Element/details"><code>&lt;details&gt;</code></a>.</li>
</ul>

<h3 id="créer_un_nouvel_élément_element-details_avec_le_modèle">Créer un nouvel élément element-details avec le modèle</h3>

<p>Ensuite, voyons comment créer un nouvel élément personnalisé, intitulé <strong><code>&lt;element-details&gt;</code></strong>, et comment utiliser <a href="/fr/docs/Web/API/Element/attachShadow"><code>Element.attachShadow</code></a> pour lui rattacher, comme <a href="/fr/docs/Web/API/ShadowRoot">racine virtuelle</a>, le fragment de document créé avec l'élément <a href="/fr/docs/Web/HTML/Element/template"><code>&lt;template&gt;</code></a> ci-dessus. Pour cela, on utilisera la même méthode qu'avec notre exemple plus simple.</p>

<pre class="brush: js">
customElements.define('element-details',
  class extends HTMLElement {
    constructor() {
      super();
      const template = document
        .getElementById('element-details-template')
        .content;
      const shadowRoot = this.attachShadow({mode: 'open'})
        .appendChild(template.cloneNode(true));
    }
  }
);
</pre>

<h3 id="utiliser_l_élément_element-details_avec_les_emplacements_nommés">Utiliser l'élément element-details avec les emplacements nommés</h3>

<p>Prenons maintenant un élément <strong><code>&lt;element-details&gt;</code></strong> et utilisons le dans notre document&nbsp;:</p>

<pre class="brush: html">
&lt;element-details&gt;
  &lt;span slot="element-name"&gt;slot&lt;/span&gt;
  &lt;span slot="description"&gt;Un emplacement dans un
    composant web que les utilisateurs pourront remplir
    avec leur propre contenu pour composer plusieurs
    arbres DOM ensemble.&lt;/span&gt;
  &lt;dl slot="attributes"&gt;
    &lt;dt&gt;name&lt;/dt&gt;
    &lt;dd&gt;Le nom de l'emplacement.&lt;/dd&gt;
  &lt;/dl&gt;
&lt;/element-details&gt;

&lt;element-details&gt;
  &lt;span slot="element-name"&gt;template&lt;/span&gt;
  &lt;span slot="description"&gt;Un mécanisme pour stocker
    du contenu côté client qui n'est pas affiché lorsque la
    page est chargée mais lors de l'exécution avec du code
    JavaScript.&lt;/span&gt;
&lt;/element-details&gt;
</pre>

<p>En voyant ce fragment, notons quelques points&nbsp;:</p>

<ul>
	<li>Ce fragment contient deux exemplaires <strong><code>&lt;element-details&gt;</code></strong> qui utilisent tous les deux l'attribut <a href="/fr/docs/Web/HTML/Global_attributes#slot"><code>slot</code></a> afin de référencer <a href="/fr/docs/Web/HTML/Element/slot#named-slot">les emplacements nommés</a> <code>"element-name"</code> et <code>"description"</code> qui sont inscrits dans <a href="/fr/docs/Web/API/ShadowRoot">la racine virtuelle</a> <code>&lt;element-details&gt;</code>.</li>
	<li>Seul le premier élément <strong><code>&lt;element-details&gt;</code></strong> fait référence à <a href="/fr/docs/Web/HTML/Element/slot#named-slot">l'emplacement nommé</a> <code>"attributes"</code>. Le deuxième élément <code><strong>&lt;element-details</strong>&gt;</code> n'y fait pas référence.</li>
	<li>Le premier élément <code>&lt;<strong>element-details&gt;</strong></code> fait référence à <a href="/fr/docs/Web/HTML/Element/slot#named-slot">l'emplacement nommé</a> <code>"attributes"</code> en utilisant un élément <a href="/fr/docs/Web/HTML/Element/dl"><code>&lt;dl&gt;</code></a> contenant comme enfants un élément <a href="/fr/docs/Web/HTML/Element/dt"><code>&lt;dt&gt;</code></a> et un élément <a href="/fr/docs/Web/HTML/Element/dd"><code>&lt;dd&gt;</code></a>.</li>
</ul>

<h3 id="mettre_le_tout_en_forme">Mettre le tout en forme</h3>

<p>Pour finir, ajoutons un peu de CSS pour les éléments <a href="/fr/docs/Web/HTML/Element/dl"><code>&lt;dl&gt;</code></a>, <a href="/fr/docs/Web/HTML/Element/dt"><code>&lt;dt&gt;</code></a> et <a href="/fr/docs/Web/HTML/Element/dd"><code>&lt;dd&gt;</code></a> de notre document&nbsp;:</p>

<pre class="brush: css">
dl { margin-left: 6px; }
dt { font-weight: bold; color: #217ac0; font-size: 110% }
dt { font-family: Consolas, "Liberation Mono", Courier }
dd { margin-left: 16px }
</pre>

<div class="hidden">
<pre class="brush: css">body { margin-top: 47px }</pre>
</div>

<h3 id="résultat">Résultat</h3>

<p>Assemblons l'ensemble des fragments pour voir le résultat final.</p>

<p>{{ EmbedLiveSample('exemple_complet', '300','400','element-details.png','') }}</p>

<p>Quelques notes à propos du résultat affiché&nbsp;:</p>

<ul>
	<li>Bien que les exemplaires des éléments <strong><code>&lt;element-details&gt;</code></strong> du document n'utilisent pas directement d'élément <a href="/fr/docs/Web/HTML/Element/details"><code>&lt;details&gt;</code></a>, ils sont rendus comme celui-ci, car <a href="/fr/docs/Web/HTML/Element/details"><code>&lt;details&gt;</code></a> <a href="/fr/docs/Web/API/ShadowRoot">la racine virtuelle</a> les peuple avec ceci.</li>
	<li>Au sein de l'élément <a href="/fr/docs/Web/HTML/Element/details"><code>&lt;details&gt;</code></a> affiché, le contenu des éléments <strong><code>&lt;element-details&gt;</code></strong> remplit <a href="/fr/docs/Web/HTML/Element/slot#named-slot">les emplacements nommés</a> de <a href="/fr/docs/Web/API/ShadowRoot">la racine virtuelle</a>. Autrement dit, l'arbre du DOM pour les éléments <strong><code>&lt;element-details&gt;</code></strong> est composé avec le contenu <a href="/fr/docs/Web/API/ShadowRoot">de la racine virtuelle</a>.</li>
	<li>Pour les deux éléments <strong><code>&lt;element-details&gt;</code></strong>, un titre <strong>Attributs</strong> est automatiquement ajouté à partir de <a href="/fr/docs/Web/API/ShadowRoot">la racine virtuelle</a> avant la position de l'emplacement nommé <code>"attributes"</code>.</li>
	<li>Étant donné que le premier élément <strong><code>&lt;element-details&gt;</code></strong> possède un élément <a href="/fr/docs/Web/HTML/Element/dl"><code>&lt;dl&gt;</code></a> qui référence explicitement <a href="/fr/docs/Web/HTML/Element/slot#named-slot">l'emplacement nommé</a> <code>"attributes"</code> depuis <a href="/fr/docs/Web/API/ShadowRoot">sa racine virtuelle</a>, les contenus de <a href="/fr/docs/Web/HTML/Element/dl"><code>&lt;dl&gt;</code></a> remplacent l'emplacement nommé <code>"attributes"</code> de <a href="/fr/docs/Web/API/ShadowRoot">la racine virtuelle</a>.</li>
	<li>Comme le second élément <strong><code>&lt;element-details&gt;</code></strong> ne fait pas explicitement référence à l'emplacement nommé <code>"attributes"</code> depuis <a href="/fr/docs/Web/API/ShadowRoot">sa racine virtuelle</a>, le contenu de cet <a href="/fr/docs/Web/HTML/Element/slot#named-slot">emplacement nommé</a> est rempli avec le contenu par défaut fourni par <a href="/fr/docs/Web/API/ShadowRoot">la racine virtuelle</a>.</li>
</ul>


<h5 id="exemple_complet">Exemple complet</h5>

<pre class="brush: html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;slot example&lt;/title&gt;
    &lt;style&gt;

      dl { margin-left: 6px; }
      dt { font-weight: bold; color: #217ac0; font-size: 110% }
      dt { font-family: Consolas, "Liberation Mono", Courier }
      dd { margin-left: 16px }

    &lt;/style&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;template id="element-details-template"&gt;
      &lt;style&gt;
      details {font-family: "Open Sans Light",Helvetica,Arial}
      .name {font-weight: bold; color: #217ac0; font-size: 120%}
      h4 { margin: 10px 0 -8px 0; }
      h4 span { background: #217ac0; padding: 2px 6px 2px 6px }
      h4 span { border: 1px solid #cee9f9; border-radius: 4px }
      h4 span { color: white }
      .attributes { margin-left: 22px; font-size: 90% }
      .attributes p { margin-left: 16px; font-style: italic }
      &lt;/style&gt;
      &lt;details&gt;
        &lt;summary&gt;
          &lt;span&gt;
            &lt;code class="name"&gt;&amp;lt;&lt;slot name="element-name"&gt;BESOIN D'UN NOM&lt;/slot&gt;&amp;gt;&lt;/code&gt;
            &lt;i class="desc"&gt;&lt;slot name="description"&gt;BESOIN D'UNE DESCRIPTION&lt;/slot&gt;&lt;/i&gt;
          &lt;/span&gt;
        &lt;/summary&gt;
        &lt;div class="attributes"&gt;
          &lt;h4&gt;&lt;span&gt;Attributs&lt;/span&gt;&lt;/h4&gt;
          &lt;slot name="attributes"&gt;&lt;p&gt;Aucun&lt;/p&gt;&lt;/slot&gt;
        &lt;/div&gt;
      &lt;/details&gt;
      &lt;hr&gt;
    &lt;/template&gt;

    &lt;element-details&gt;
      &lt;span slot="element-name"&gt;slot&lt;/span&gt;
      &lt;span slot="description"&gt;Un emplacement dans un
        composant web que les utilisateurs pourront remplir
        avec leur propre contenu pour composer plusieurs
        arbres DOM ensemble.&lt;/span&gt;
      &lt;dl slot="attributes"&gt;
        &lt;dt&gt;name&lt;/dt&gt;
        &lt;dd&gt;Le nom de l'emplacement.&lt;/dd&gt;
      &lt;/dl&gt;
    &lt;/element-details&gt;

    &lt;element-details&gt;
      &lt;span slot="element-name"&gt;template&lt;/span&gt;
      &lt;span slot="description"&gt;Un mécanisme pour stocker
        du contenu côté client qui n'est pas affiché lorsque la
        page est chargée mais lors de l'exécution avec du code
        JavaScript.&lt;/span&gt;
    &lt;/element-details&gt;

    &lt;script&gt;
    customElements.define('element-details',
      class extends HTMLElement {
        constructor() {
          super();
          const template = document
            .getElementById('element-details-template')
            .content;
          const shadowRoot = this.attachShadow({mode: 'open'})
            .appendChild(template.cloneNode(true));
        }
      })
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
</div>