0Pricing
JavaScript Academy · レッスン

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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. カスタム要素を定義する
  2. ライフサイクルコールバック
  3. Shadow DOM とカプセル化
  4. テンプレートとスロット
← JavaScript Academyに戻る