🚀
Shadow DOM の仕様について
Shadow DOM の概要
Shadow DOM とは、Web コンポーネントにおける「カプセル化された DOM」のことを指します。通常の DOM はグローバルにアクセス可能ですが、Shadow DOM を利用すると、内部構造を外部から隠すことができます。この特性により、次のようなメリットが得られます。
✅ スタイルやスクリプトの競合を防ぐ
✅ コンポーネントの再利用性を向上させる
Shadow DOM には open と closed の 2 種類のモードがあります。これらは、外部からのアクセス制御の度合いに影響を与えます。
open モード
open モードでは、Shadow DOM が外部からアクセス可能になります。shadowRoot プロパティを介して操作できるため、拡張性が求められるコンポーネントに適しています。
特徴:
- shadowRoot プロパティが公開され、外部から DOM にアクセス可能
- 他のスクリプトから Shadow DOM 内部を変更できる
const shadowHost = document.querySelector('#shadow-host');
const shadowRoot = shadowHost.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `<p>Shadow DOM</p>`;
console.log(shadowHost.shadowRoot == shadowRoot); // true - documentからアクセスできる
<template>要素を使う場合
<div class="shadow-host">
<template shadowrootmode="open">
<p>Shadow DOM</p>
</template>
</div>
const shadowHost = document.querySelector(".shadow-host");
const shadowRoot = shadowHost.shadowRoot;
console.log(shadowRoot.innerText);
closed モード
このモードでは、shadowRoot プロパティが null を返し、外部からのアクセスができなくなります。これにより、意図しないスクリプトによる改変を防ぐことができます。
const shadowHost = document.querySelector('#shadow-host');
const shadowRoot = shadowHost.attachShadow({ mode: 'closed' });
shadowRoot.innerHTML = `<p>Shadow DOM</p>`;
console.log(shadowHost.shadowRoot); // null が返される
console.log(shadowRoot); // shadowRootという変数からのみ、操作可能
<template>要素を使う場合
<div class="shadow-host">
<template shadowrootmode="closed">
<p>Shadow DOM</p>
</template>
</div>
// 外部からアクセスできなくなるので、安全
Shadow DOM の基本的な使い方
Shadow DOM に CSS を適用する方法
Shadow DOM 内部のスタイルは、通常の CSS とは異なり、外部のスタイルの影響を受けません。適用する方法は大きく分けて 2 つあります。
const host = document.querySelector("#host");
const shadow = host.attachShadow({ mode: "open" });
const sheet = new CSSStyleSheet();
sheet.replaceSync("span { color: red; border: 2px dotted black;}");
shadow.adoptedStyleSheets = [sheet];
const span = document.createElement("span");
span.textContent = "I'm in the shadow DOM";
shadow.appendChild(span);
Shadow DOM はセキュリティ機能ではない
Shadow DOM はセキュリティ機能ではありません。これは、CSS のスコープを設定し、DOM ツリーをコンポーネントの中に隠すための軽量なツールです。真のセキュリティ境界が必要な場合は、
<iframe>
を使用します。
https://web.dev/articles/shadowdom-v1?hl=ja#faq
簡易的なiframe sandboxのコードは、こちら に置いておきます
参考文献
Discussion
Shadow DOM はセキュリティ機能として設計されていません。Shadow DOMの外部/内部間で定義されたJSやCSSの影響を互いに受けないようにし、コンポーネントのカプセル化を実現するための機能です。
そのため、「基本的な使い方」で例示したようなclosedモードを利用して機密情報を保護する目的には適していません。
教えていただきありがとうございます。
すぐ修正します
ページ読み込み時の一番最初に
Element.prototype.attachShadow
を上書きされると closed モード にできなくすることもできるので そこまで安全でもないですね。盲点でした...
教えていただきありがとうございます