Shadow DOM en JavaScript
Cet article explique le Shadow DOM en JavaScript.
YouTube Video
javascript-html-shadow-dom.html
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <title>JavaScript & HTML</title>
6 <style>
7 * {
8 box-sizing: border-box;
9 }
10
11 body {
12 margin: 0;
13 padding: 1em;
14 padding-bottom: 10em;
15 font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
16 background-color: #f7f9fc;
17 color: #333;
18 line-height: 1.6;
19 }
20
21 .container {
22 max-width: 800px;
23 margin: 0 auto;
24 padding: 1em;
25 background-color: #ffffff;
26 border: 1px solid #ccc;
27 border-radius: 10px;
28 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
29 }
30
31 h1, h2 {
32 font-size: 1.2rem;
33 color: #007bff;
34 margin-top: 0.5em;
35 margin-bottom: 0.5em;
36 border-left: 5px solid #007bff;
37 padding-left: 0.6em;
38 background-color: #e9f2ff;
39 }
40
41 button {
42 display: block;
43 margin: 1em auto;
44 padding: 0.75em 1.5em;
45 font-size: 1rem;
46 background-color: #007bff;
47 color: white;
48 border: none;
49 border-radius: 6px;
50 cursor: pointer;
51 transition: background-color 0.3s ease;
52 }
53
54 button:hover {
55 background-color: #0056b3;
56 }
57
58 #output {
59 margin-top: 1em;
60 background-color: #1e1e1e;
61 color: #0f0;
62 padding: 1em;
63 border-radius: 8px;
64 min-height: 200px;
65 font-family: Consolas, monospace;
66 font-size: 0.95rem;
67 overflow-y: auto;
68 white-space: pre-wrap;
69 }
70
71 .highlight {
72 outline: 3px solid #ffc107; /* yellow border */
73 background-color: #fff8e1; /* soft yellow background */
74 transition: background-color 0.3s ease, outline 0.3s ease;
75 }
76
77 .active {
78 background-color: #28a745; /* green background */
79 color: #fff;
80 box-shadow: 0 0 10px rgba(40, 167, 69, 0.5);
81 transition: background-color 0.3s ease, box-shadow 0.3s ease;
82 }
83 </style>
84</head>
85<body>
86 <div class="container">
87 <h2>HTML Sample</h2>
88 <div id="content"></div>
89 <div id="shadow-host">Shadow Root Element</div>
90 <my-card></my-card>
91 </div>
92
93 <div class="container">
94 <h1>JavaScript Console</h1>
95 <button id="executeBtn">Execute</button>
96 <div id="output"></div>
97 </div>
98
99 <div>
100 <h2>Slot Sample</h2>
101 <my-element>
102 <h3 slot="header">Header Content</h1>
103 <p slot="content">Main Content</p>
104 </my-element>
105 </div>
106
107 <script>
108 // Override console.log to display messages in the #output element
109 (function () {
110 const originalLog = console.log;
111 console.log = function (...args) {
112 originalLog.apply(console, args);
113 const output = document.getElementById('output');
114 output.textContent += args.map(String).join(' ') + '\n';
115 };
116 })();
117
118 document.getElementById('executeBtn').addEventListener('click', () => {
119 // Prevent multiple loads
120 if (document.getElementById('externalScript')) return;
121
122 const script = document.createElement('script');
123 script.src = 'javascript-html-shadow-dom.js';
124 script.id = 'externalScript';
125 //script.onload = () => console.log('javascript-html-shadow-dom.js loaded and executed.');
126 //script.onerror = () => console.log('Failed to load javascript-html-shadow-dom.js.');
127 document.body.appendChild(script);
128 });
129 </script>
130</body>
131</html>
Comprendre le Shadow DOM
Le Shadow DOM
est une fonctionnalité puissante du standard des Web Components qui permet l'encapsulation des styles et de la structure DOM au sein des composants. Cette fonctionnalité empêche les interférences de styles et de scripts entre les composants et le document principal.
Shadow DOM
en JavaScript
Le Shadow DOM
offre un moyen de créer un arbre DOM limité associé à un élément DOM classique. Cet arbre shadow est isolé du document global : les styles et scripts externes ne l'influencent pas, et ses styles et scripts internes ne s'échappent pas.
Par exemple, si vous créez un composant bouton personnalisé en utilisant le Shadow DOM
, ses styles n'interféreront pas avec les autres éléments de la page. De même, les éléments portant le même nom de classe n'entreront pas en conflit.
Le contenu HTML régulier en dehors du Shadow DOM
est appelé le Light DOM
.
Avantages du Shadow DOM
-
Encapsulation
- Le
Shadow DOM
sépare le style et la fonctionnalité, empêchant les conflits avec les styles et scripts globaux.
- Le
-
Réutilisabilité
- Les composants construits avec le
Shadow DOM
peuvent être réutilisés dans divers projets sans se soucier des conflits de styles.
- Les composants construits avec le
-
Facilité de maintenance
- L'encapsulation rend la logique et le style du composant autonomes, ce qui facilite le débogage et la maintenance.
Créer un Shadow DOM
Pour utiliser le Shadow DOM
, vous devez attacher une racine shadow à un élément HTML. Voici un exemple simple :.
1// Select the host element
2const hostElement = document.querySelector('#shadow-host');
3
4// Attach a shadow root
5const shadowRoot = hostElement.attachShadow({ mode: 'open' });
Explication
Ce code comprend les éléments suivants :.
-
Élément hôte
- Un élément DOM classique auquel la racine shadow est attachée (dans ce cas,
#shadow-host
).
- Un élément DOM classique auquel la racine shadow est attachée (dans ce cas,
-
Racine shadow
- La racine de l'arbre shadow créée avec
attachShadow
.
- La racine de l'arbre shadow créée avec
-
Mode
- En mode
open
, le JavaScript externe peut accéder à la racine shadow viaelement.shadowRoot
. En revanche, le modeclosed
n'autorise pas l'accès.
- En mode
Styliser avec le Shadow DOM
Shadow DOM
a son propre périmètre de styles. Les styles définis dans l'arbre shadow s'appliquent uniquement aux éléments de cet arbre. Voici un exemple :.
1// Add content to the shadow root
2shadowRoot.innerHTML = `
3 <style>
4 p {
5 color: green;
6 }
7 </style>
8 <p>Scoped style inside Shadow DOM.</p>
9`;
Même s'il y a des styles conflictuels dans le document principal, ils n'affectent pas le paragraphe à l'intérieur de l'arbre shadow.
1const content = document.getElementById('content');
2content.innerHTML = `
3 <style>
4 p {
5 color: red;
6 }
7 </style>
8 <p>This is in the main DOM.</p>
9`;
- Le paragraphe à l'intérieur du
Shadow DOM
reste vert, tandis que celui à l'extérieur est rouge.
Les événements dans le Shadow DOM
Les événements dans le Shadow DOM
sont similaires aux événements normaux du DOM, mais peuvent se comporter différemment en termes de propagation à cause de l'encapsulation.
Voici un exemple :.
1// Add an event listener inside Shadow DOM
2shadowRoot.innerHTML = `
3 <div id="button-container">
4 <button id="shadow-button">Click Me</button>
5 </div>
6`;
7
8shadowRoot.querySelector('#shadow-button').addEventListener('click', (event) => {
9 console.log('Button : Button clicked inside Shadow DOM');
10 console.log(event.target);
11});
12
13shadowRoot.querySelector('#button-container').addEventListener('click', (event) => {
14 console.log('Container : Button clicked inside Shadow DOM');
15 console.log(event.target);
16});
17
18hostElement.addEventListener('click', (event) => {
19 console.log('Event bubbled to the host element');
20 console.log(event.target);
21});
22
23document.addEventListener('click', (event) => {
24 console.log('Document listener');
25 console.log(event.target);
26});
- Lorsque le bouton est cliqué, les deux écouteurs sont déclenchés, ce qui démontre le comportement de la propagation des événements.
- Lorsqu'un événement provenant du
Shadow DOM
remonte vers leLight DOM
, la propriététarget
de l'événement est réécrite en tant qu'élément hôte au lieu de la source d'origine.- Dans cet exemple,
event.target
à l'intérieur duShadow DOM
est le véritable élémentbutton
, mais à l'extérieur duShadow DOM
, il est remplacé par l'élément hôtediv
.
- Dans cet exemple,
Shadow DOM
et éléments personnalisés
Shadow DOM
et les éléments personnalisés sont des composants clés des Web Components
. Ce sont des technologies utilisées pour créer des composants UI réutilisables et encapsulés.
1class MyCard extends HTMLElement {
2 constructor() {
3 super();
4 const shadow = this.attachShadow({ mode: 'open' });
5 shadow.innerHTML = `
6 <style>
7 p {
8 color: blue;
9 }
10 </style>
11 <p>I'm inside shadow DOM</p>
12 `;
13 }
14}
15
16customElements.define('my-card', MyCard);
Le document principal contient un HTML comme celui-ci :.
1<my-card></my-card>
- En utilisant le
Shadow DOM
dans des éléments personnalisés, vous pouvez créer des composants réutilisables qui résistent aux conflits de styles. Dans ce code, une balise nomméemy-card
est créée et associée à la classeMyCard
. L'élément<p>
à l'intérieur demy-card
n'est pas affecté par les styles externes et s'affiche toujours en bleu.
Slots : distribution du contenu du Light DOM
Les slots vous permettent de projeter le contenu du Light DOM
dans le Shadow DOM
. Voici un exemple :.
1class MyElement extends HTMLElement {
2 constructor() {
3 super();
4 const shadow = this.attachShadow({ mode: 'open' });
5
6 shadow.innerHTML = `
7 <style>
8 .container {
9 border: 2px solid #ccc;
10 padding: 16px;
11 border-radius: 8px;
12 font-family: sans-serif;
13 }
14 .header {
15 font-size: 1.2em;
16 color: darkblue;
17 margin-bottom: 8px;
18 }
19 .content {
20 font-size: 1em;
21 color: #333;
22 }
23 </style>
24 <div class="container">
25 <div class="header">
26 <slot name="header"></slot>
27 </div>
28 <div class="content">
29 <slot name="content"></slot>
30 </div>
31 </div>
32 `;
33 }
34}
35
36customElements.define('my-element', MyElement);
Le document principal contient un HTML comme celui-ci :.
1<my-element>
2 <h3 slot="header">Header Content</h1>
3 <p slot="content">Main Content</p>
4</my-element>
- L'élément
slot
à l'intérieur duShadow DOM
affiche le contenu duLight DOM
qui possède l'attributslot
correspondant.
Conclusion
Shadow DOM
est un outil essentiel pour créer des composants web robustes, réutilisables et maintenables. En encapsulant les styles et les fonctionnalités, il réduit les risques de conflits et simplifie la gestion du code.
Vous pouvez suivre l'article ci-dessus avec Visual Studio Code sur notre chaîne YouTube. Veuillez également consulter la chaîne YouTube.