Shadow DOM - Web Components を構成する技術
by えーじ / Eiji Kitamura
この記事は webcomponents.org の記 事とのクロスポス トです。
Shadow DOM を利用すると、DOM 要素に、ウェブページの他の部分とは切り離された、 ノード内だけで有効なスタイルやマークアップを含んだ DOM ツリーを追加することがで きます。この記事と動画では、この Shadow DOM について解説します。
Shadow DOM とはなにか? #
こちらは HTML5 の video タグで表示された動画です。ご覧頂けるとお分かりのように、 コードは video タグのみという単純さでありながら、動画そのものだけでなく、制御用 の UI も表示することができています。
<video src="http://craftymind.com/factory/html5video/BigBuckBunny_640x360.mp4" controls></video>
実は Chrome で DevTools を開いて、'Show user agent shadow DOM'
オプションを on
にすると、この制御用 UI がどのようにできているか確認することができます。
この制御用 UI が、実際は HTML でできていることがお分かりでしょうか?これが Shadow DOM の一例です。
Shadow DOM が素晴らしいのは、実はこの機能がウェブ開発者にも使える、ということで す。
Shadow DOM の構造 #
Shadow Root を持った要素は Shadow Host と呼ばれます。Shadow Root は通常の DOM 要 素と同様に扱えるため、任意のノードを追加することもできます。
Shadow DOM では、すべてのマークアップと CSS が要素内にスコープされます。言い換え ると、Shadow Root 内で定義された CSS は親ドキュメントに影響を与えず、親ドキュメ ントの CSS が誤って Shadow Root 内に影響を与えることもありません。
Shadow DOM の作り方 #
Shadow DOM を作るには、任意の DOM 要素に対して .createShadowRoot()
を呼び出
し、Shadow Root を作ります。この Shadow Root オブジェクトに要素を足していくこと
で、Shadow DOM を構築していくことができます。
<div id="host"></div>
var host = document.querySelector('#host');
var root = host.createShadowRoot(); // Shadow Root を作る
var div = document.createElement('div');
div.textContent = 'This is Shadow DOM';
root.appendChild(div); // Shadow Root に要素を追加
Shadow Root に追加された要素はクエリすることもできません。この場合、
document.querySelector('#host div')
は null
になります。
Shadow DOM 内に Shadow Host のコンテンツを表示する #
Shadow DOM 内に Shadow Host の子要素を表示したい場合があると思います。例えば Shadow DOM によってスタイルを与えられているネームタグのような要素を考えてみま しょう。外部からの入力で文字だけ変更できると便利ですよね。
<div id="nameTag">Bob</div>
これを実現するには、<content>
要素を用います。
var host = document.querySelector('#host');
var root = host.createShadowRoot();
var content = document.createElement('content');
content.setAttribute('select', 'h1'); //<content select="h1"></content>
root.appendChild(content);
<div id="host">
<h1>This is Shadow DOM</h1>
<div>
<content>
要素に select
属性として Shadow Host から取り上げたいノードを指し
示す CSS セレクタを与えることで、その要素が <content>
の位置に挿入されます。
なお、<content>
要素で指定できるのは、Shadow Host の直接の子孫となる要素を示す
CSS セレクタのみです。つまり以下のように、子孫の子孫を示すようなことはできませ
ん。
<div id="host">
<div class="child">
<h1>This is Shadow DOM</h1>
</div>
</div>
<content select=".child h1"></content> // これはダメ
Template と組み合わせる #
Shadow DOM は素晴らしいですが、構築のためにいちいち命令的に DOM ツリーを構築する JavaScript を書くのは楽ではありませんし、デザイナーが入ってくる余地もありませ ん。
そこで登場するのが Template 要素です。Template 要素を活用することで、Shadow DOM の構築が宣言的に行いましょう。Template 要素については、前回のポス トを参考にして下 さい。
<template id="template"> // <template> の中身が Shadow DOM になる
<style>
...
</style>
<div id="container">
<img src="http://webcomponents.org/img/logo.svg">
<content select="h1"></content> // h1 をここに挿入
</div>
</template>
<div id="host">
<h1>This is Shadow DOM</h1>
</div>
var host = document.querySelector('#host');
// Shadow Root を作る
var root = host.createShadowRoot();
var template = document.querySelector('#template');
// <template> をコピー
var clone = document.importNode(template.content, true);
// Shadow Root に追加
root.appendChild(clone);
実際のコードはこちらでご覧頂けます。
ブラウザサポート状況 #
Shadow DOM は 2014 年 10 月現在 Chrome, Opera, フラグ付きなら Firefox でもサポー トされています。最新のサポート状況は chromestatus.com または caniuse.com で チェックしてみて下さい。ポリフィルとして platform.js (2014 年 11 月から webcomponents.js に名称変更予 定) も利用できます。
まとめ #
いかがでしたでしょうか?Shadow DOM は今回記事にした内容の他にも、外部からのスタ イリングやイベントの扱い方、複数の Shadow Root の扱い方など、非常に複雑な仕様が 盛りだくさんです。
Shadow DOM についてより詳しく知りたいという方は、下記のドキュメントを参考にして ください。
Subscribe via RSS