HTML5: Shadow DOMについて

Web Componentsの機能の一つ Shadow DOMについて説明します.

Shadow DOMとは?

外部から影響を受けない, 外部に影響を与えない隔離された要素です. 「カプセル化されたHTML要素」みたいな感じです.

Shadow DOMの誕生背景

なぜShadow DOMが出てきたかについて説明します.

CSS, JavaScriptは, 全要素に対して影響が及ぶという性質があります.(グローバルに影響を与える) ある箇所を修正したら, 予期せぬ箇所にも影響が出てしまうことがよく起こりますが, これはバグを生み出しやすくとてもよくないです. 例をあげると,

.hoge {
  font-size: 30px;
}

と書くと, hogeをclass属性に持つ要素の文字サイズが30pxになります. 偶然にも他の部分でhogeクラスセレクターを使っていたとしたらそのセレクターにも影響を与えてしまいます. 仮に, 他の人が作ったコンテンツが隔離されて使用できれば, 同じセレクターを使ったとしても, 問題がなくなります.

フロント側が年々複雑になったことにより, スタイルシート, JavaScriptが肥大化した結果, コンテンツを互いに隔離したいという要望が高まり, Shadow DOMが誕生しました.

使い方

Shadow DOMを作るにはcreateShadowRootAPIを使います. 以下, Shadow DOM版Hello Worldです.

  <div id="shadow"></div>

  <script>
  function insertShadow() {
    // Shadow DOMの作成
    var shadow = document.querySelector('#shadow').createShadowRoot();
    shadow.textContent = 'Hello world';
  }
  insertShadow();
  </script>

Shadow DOMが挿入され, Hello Worldと表示されます.

上の例ではShadow DOMの良さが全く現れていないので, もう1つ例をあげます. Shadow DOMは, templateと組み合わせることでより強力に使うことが出来ます.

  <div id="hello1">Hello world1</div>
  <div id="hello2"></div>
  <template id="templateHello">
    <!-- ここのスタイルは, 外部に影響を与えない! -->
    <style>
      div {
        color: red;
      }
    </style>
    <div>Hello world2</div>
  </template>
  <script>
  function insertShadow2() {
    var target = document.querySelector('#hello2').createShadowRoot(),
        hello = document.querySelector('#templateHello').content;
    target.appendChild(hello.cloneNode(true));
  }
  insertShadow2();
  </script>

上記のように書くと, Hello world1は黒いままで, color: red;は効きません. なぜなら, Shadow DOMでtemplateの中身は外部と隔離されているためです. これがShadow DOMです.

まとめ

Shadow DOMの概要, 簡単な使い方について書いてみました.

2014年現在は実用するには厳しいですが, 2017年くらいには実用的になっていると思います(なんとなく). 今すぐに使いたい人は https://github.com/Polymer/polymer などのpolyfillを使うのがいいかと思います.

参考サイト