HTML5

Shadow DOM に触れてみた

More than 3 years have passed since last update.

HTML5 Conference 2013 で聞いた「Web をまともにしたいので Shadow DOM と Web Components をつくってます」(動画参照)。
この講義を見て、調べながら実際に ShadowDOM を使ってWebComponents をつくってみました。

講義中にて紹介のあった、Polymer を使って自作のエレメント x-helloworld を実装してみました。

Polymer のインストール

Polymer は、WebComponents を簡単に使えるようにするフレームワークのような、ライブラリのような、コンポーネント集でもあるようなものと、講義中で紹介されています。

今回は最低限のライブラリのみ使用して、最低限のコンポーネントを作成しました。

次のコマンドでPolymerをインストールします。(bowerをインストールしていないと動きません)

$ mkdir htdocs
$ cd htdocs/
$ bower install --save Polymer/polymer

そうすると、htdocs ディレクトリの中に、次のディレクトリとライブラリが生成されます。

  • <htdocs>/bower_components/platform/
  • <htdocs>/bower_components/polymer/

この2つのコンポーネントが必要なようです。

エレメント x-helloworld を定義する

今回、次のパスにエレメント x-helloworld を実装してみます。

<htdocs>/customElms/x-helloworld/x-helloworld.html
<link rel="import" href="../../bower_components/polymer/polymer.html" />
<polymer-element name="x-helloworld" noscript>
    <template>
        <link rel="stylesheet" href="x-helloworld.css" />
        <shadow>
            <h1>Hello World!!</h1>
            <p>
                Shadow DOM を使ってみました。<br />
            </p>
        </shadow>
    </template>
</polymer-element>

このタグ x-helloworld が再現するDOM構造を <shadow> の中に定義しています。これに対して、次のCSSを読み込んでスタイルを設定しています。

<htdocs>/customElms/x-helloworld/x-helloworld.css
:host {
  display:block;
  background-color:#ff0000;
  border-radius:5px;
  padding:1em;
  height: auto;
  width:300px;
  white-space: nowrap;
  text-align:left;
}
:host h1{
  color:#fff;
  font-size:16px;
  display:block;
  margin:0;
}
:host p{
  color:#fff;
  font-size:12px;
  display:block;
  margin:0;
}

:host は、x-helloworld 自体を指しています。

エレメント x-helloworld を呼び出して配置する

<htdocs>/index.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>x-helloworld エレメントを自作するテスト</title>
        <script src="bower_components/platform/platform.js"></script>
        <link rel="import" href="customElms/x-helloworld/x-helloworld.html" />
    </head>
    <body>
        <p>1. x-helloworld element</p>
        <x-helloworld></x-helloworld>
        <p>2. x-helloworld element</p>
        <x-helloworld></x-helloworld>
    </body>
</html>

<link rel="import" href="customElms/x-helloworld/x-helloworld.html" /> この記述が、先ほど定義したカスタムエレメント x-helloworld を読み込んでいる部分です。

bodyセクションにある <x-helloworld></x-helloworld> の記述で、作成したタグを呼び出して画面に配置しています。

Google Chrome で表示した結果は次のような画面です。

Google Chromeでの表示結果

<shadow> に書いたDOM構造が、x-helloworld タグそれぞれに呼び出され、再現されているのがわかります。

まとめ

いまいちちゃんと理解できたような気はしてないですが、一応の動作はできたと思います。今回やってみたのはすごく静的な表示のものでしたが、「目標はGmailを数行のタグだけで配置できるようになりたい」と言ってるわけだし、JavaScriptで動作するアプリケーションのインターフェイスを1つエレメントに閉じ込めて実装するようなことが可能になるのだと思います。

講義の最後に、「誰も知らないようなタグがたくさん作られたら、ウェブはカオスになってしまうのではないか」的な質問をしている方がいました。これには僕も同感ですが、そうならないために、ウェブを作るひとは、ドキュメント と アプリケーション の扱いについてよく意識する必要があるのではないかと思います。

"ドキュメント構造とスタイルの分離" の実装は、WWWに広く普及したと思います。HTML5によってウェブページにアプリケーションのインターフェイスが持ち込まれたことにより、ウェブページは再びセマンティックではなくなろうとしています。HTML5アプリケーションの混在した、あるいはHTML5アプリケーションに内包されてしまったウェブドキュメントは、特定の環境(PCやスマートフォン)のためのものになりがちです。例えばスクリーンリーダーなどに頼らざるを得ないウェブユーザーにとっては、とても使いづらいものになっています。Web Components は、ウェブドキュメントとウェブアプリケーションの分離を可能にし、こうした問題を解決できるのではないか、という期待感を持ちました。

ちなみに、 Shadow DOM はまだ策定中の仕様なので、一部のブラウザでしか動作しないようですが、今回作成してみたコードは、Google Chrome 31.0 と、Firefox 26.0 でも動作しました。Polymer には、IEなどの Shadow DOM に未対応なブラウザに対応するために、Polyfill というライブラリ(?) が付属しているそうですが、今回はややこしくなりそうなので使いませんでした。

今回試してみたソースは下記にアップしました。参考になれば幸いです。

※この記事はこちらにアーカイブしました。→ http://www.pxt.jp/ja/diary/article/286/