Shadow DOM とカプセル化
Shadow root 内でスタイルとマークアップを分離します。
「Shadow DOM とカプセル化」はCoddyKit上の無料JavaScript Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJavaScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 JavaScript Academyコースには全4レッスンが含まれています。
Shadow DOM とは
Shadow DOM を使うと、要素に非公開でカプセル化された DOM ツリーを持たせることができます。その内部のマークアップとスタイルは、ページの他の部分から分離されます。
- 外部の CSS が内部に入り込むことはありません。
- 内部の CSS が外部に漏れ出すことはありません。
- 内部構造は通常の DOM クエリから隠されます。
attachShadow
this.attachShadow({ mode: 'open' }) を呼び出すと、シャドーツリーを作成できます。通常のノードと同じように内容を追加できる シャドールートが返されます。
class FancyBox extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
}
customElements.define('fancy-box', FancyBox);open と closed のモード
mode オプションで外部からのアクセス方法を制御します。
'open'—element.shadowRootからルートにアクセスできます。'closed'—element.shadowRootはnullを返し、参照を保持するのはコードだけになります。
デバッグしやすいため、ほとんどのコンポーネントでは 'open' を使用します。
const root = this.attachShadow({ mode: 'open' });
// Later, from outside:
// myEl.shadowRoot -> the shadow root (open)
// closed mode would give null hereシャドールートへの追加
shadowRoot.innerHTML に値を設定して、カプセル化されたコンテンツを構築します。このマークアップは document.querySelector からは見えません。
class FancyBox extends HTMLElement {
constructor() {
super();
const root = this.attachShadow({ mode: 'open' });
root.innerHTML = '<p>I live inside the shadow DOM</p>';
}
}
customElements.define('fancy-box', FancyBox);スコープ付きスタイル
シャドールート内の style タグは、そのルートだけに影響します。コンポーネントの外部にある同じセレクターには影響せず、ページのスタイルが内部に入り込むこともありません。
root.innerHTML =
'<style>p { color: rebeccapurple; }</style>' +
'<p>Only this paragraph is purple.</p>';
// A <p> elsewhere on the page is NOT affected.:host セレクター
シャドースタイル内の :host は、カスタム要素自身(シャドーツリーのホスト)を対象にします。コンポーネントの外側のボックスにスタイルを適用するために使用します。
root.innerHTML =
'<style>' +
':host { display: block; border: 1px solid gray; }' +
':host(.active) { border-color: green; }' +
'</style>' +
'<slot></slot>';スタイルの分離を実際に確認する
カプセル化により、コンポーネントの作成者とページの作成者がクラス名をめぐって競合することはなくなります。あるコンポーネント内の .title ルールが、別の場所にある .title に影響することはありません。
- グローバル CSS の衝突がありません。
- 単純で汎用的なセレクターを再び安全に使えます。
シャドールート内の検索
内部ノードにアクセスするには、document ではなくシャドールートを検索します。シャドールートでは、同じクエリメソッドを使用できます。
class ToggleButton extends HTMLElement {
constructor() {
super();
const root = this.attachShadow({ mode: 'open' });
root.innerHTML = '<button>Off</button>';
this.btn = root.querySelector('button');
}
}
customElements.define('toggle-button', ToggleButton);イベントは境界を越える
click など多くのイベントは Shadow DOM の外側へバブルしますが、外部のリスナーからは内部ノードではなくホスト要素が見えるようにリターゲティングされます。これによりカプセル化が保たれます。
// Outside listener sees event.target as <toggle-button>,
// not the inner <button>.
document.querySelector('toggle-button')
.addEventListener('click', e => {
console.log(e.target.tagName); // TOGGLE-BUTTON
});継承可能なスタイル
color や font-family など一部の CSS プロパティは、継承が合成ツリーを通って流れるため、シャドー境界を越えて継承されます。継承を利用するか、CSS カスタムプロパティを使うことで、ページの外観に合わせることができます。
// :host { color: inherit; }
// CSS custom properties also pierce the boundary:
// :host { color: var(--text-color, black); }Shadow DOM を使う場面
再利用可能なウィジェットでスタイルとマークアップをしっかり分離する必要がある場合は、Shadow DOM を使用してください。コンポーネントにページのグローバルスタイルを自由に継承・適用させたい場合は、使用しないほうがよいでしょう。
簡単な確認
Shadow DOM について、理解度を確認しましょう。
まとめ
Shadow DOM について学びました。
attachShadow({ mode })で分離されたツリーを作成します。'open'ではshadowRootが公開され、'closed'では隠されます。- 内部の
styleタグはスコープ化され、:hostで要素自体にスタイルを適用します。 - クエリは document ではなくシャドールートに対して実行します。
- イベントはカプセル化を保つためにリターゲティングされます。
次は、テンプレートとスロットを使ってマークアップを再利用します。
よくある質問
「Shadow DOM とカプセル化」レッスンは無料ですか?
はい。「Shadow DOM とカプセル化」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、JavaScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 JavaScript Academyコースには全4レッスンが含まれています。
「Shadow DOM とカプセル化」で何を学びますか?
Shadow root 内でスタイルとマークアップを分離します。 ブラウザで直接実行するハンズオンコードでJavaScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
JavaScript Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJavaScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「Shadow DOM とカプセル化」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJavaScript Academyレッスンでコードを書いて実行できますか?
はい。すべてのJavaScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- カスタム要素を定義する
- ライフサイクルコールバック
- Shadow DOM とカプセル化
- テンプレートとスロット