WWW Watch

iframe 要素の seamless 属性を試してみた

WebKit Nightly Builds が iframe 要素に追加された seamless 属性に対応したとのことなので、早速どんな感じになるのか確認してみました。現在公開されている WebKit Nightly Builds の最新版、及び Google Chrome も、開発者向けビルド (Dev channel) の最新版 「21.0.1155.2」 で動作しているのが確認できました。

WebKit Nightly BuildsWebKit Nightly Buildsが iframe 要素に追加された seamless 属性に対応したとのことなので、早速どんな感じになるのか確認してみました。

現在公開されている WebKit Nightly Builds の最新版、及び Google Chrome も、開発者向けビルド (Dev channel) の最新版 「21.0.1155.2」 で動作しているのが確認できました。インストール済みの方は下記にデモページを置いておきましたので確認できるかと思います。

iframe 要素の seamless 属性とは

seamless 属性は HTML5 で iframe 要素の属性として新たに追加されました。W3C の仕様的には下記のような感じです。

The seamless attribute is a boolean attribute. When specified, it indicates that the iframe element's browsing context is to be rendered in a manner that makes it appear to be part of the containing document (seamlessly included in the parent document).

Specifically, when the attribute is set on an iframe element whose owner Document's browsing context did not have the sandboxed seamless iframes flag set when that Document was created, and while either the browsing context's active document has the same origin as the iframe element's document, or the browsing context's active document's address has the same origin as the iframe element's document, or the browsing context's active document is an iframe srcdoc document, the following requirements apply:

4.8.2 The iframe element : HTML5 W3C Working Draft 29 March 2012 から引用

seamless 属性が指定されると、その iframe 要素で読み込まれたコンテンツは、親ドキュメントに、まるでそのドキュメントの一部のようにレンダリングされますよと。

で、条件付き ※ ではありますが、下記のような要件が適用されます。仕様書はちょっと難しい書き方をしているのでポイントを超簡略に書くと下記の 2点が特徴的です。(仕様を詳しく読みたい方は HTML5.JP さんが翻訳を公開されていますのでそちらを見ていただくとよろしいかと)

iframe 内に読み込まれたリンクを開く場合、親ドキュメント上のリンクとして開く

通常は iframe 要素で読み込んだコンテンツ内のリンクに target 属性がなければ、リンクは iframe 内で展開されますが、seamless 属性を指定した場合は、常に親ドキュメントをターゲットにリンクを開きます。もし iframe 内でリンクを開きたい場合は、リンクに target="_self" を指定することで可能です。

親ドキュメントで指定したスタイルは iframe 内の要素にも継承する

従来、iframe で読み込んだコンテンツに対して、親ドキュメントからスタイルを適用することはできませんでしたが、seamless 属性を指定した場合は iframe 内で読み込んだコンテンツ内の各要素も、親ドキュメント上にあるものと同様に、スタイルを適用することができます。

「まるで親ドキュメント上に直接あるかのように、iframe 要素内のコンテンツが振る舞うよ」 と言っている意味がわかるかと思います。

※ 条件としては、親ドキュメントと、iframe 内のコンテンツが同一のオリジンを持つこと (要するに同じドメイン上にあるファイルを、親と同一のスキームで読み込んでいればいい)、また、sandbox 属性が同時に指定されている場合、リンクは iframe 内で展開されます。

実際にどうなるのか

ということで、実際にどうなるかをデモページのキャプチャを使って簡単に。

まず該当するソースを下記に示しますが、親となるドキュメントはこんな感じ。

<!DOCTYPE html>
<html>
  <head>
  <meta charset="utf-8" />
  <title>seamless 属性</title>
  <style>
    /* ここに iframe 内で読み込んだコンテンツ内の要素を対象に CSS を書いちゃう */
    nav {
      background: #0099cc;
      background: -moz-linear-gradient(top,#0099cc 0%,#006699);
      background: -webkit-gradient(linear, left top, left bottom, from(#0099cc), to(#006699));
      background: linear-gradient(top,#0099cc 0%,#006699);
      border: 1px solid #ddd;
      border-radius: 4px;
      margin: 0 1em;
      padding: 10px;
    }
    #mainNav {
      margin: 0;
      padding: 0;
    }
    #mainNav li {
      display: inline-block;
      list-style: none;
      margin-right: 10px;
    }
    /* …省略… */
  </style>
  </head>
  <body>
 
  <nav>
    <iframe src="nav.html" seamless></iframe>
  </nav>
 
  </body>
</html>

iframe 要素で読み込んでいる HTML (nav.html) の中身は単純に下記のような感じ。

<ul id="mainNav">
  <li><a href="http://hyper-text.org/">Home</a></li>
  <li><a href="./">Navi02</a></li>
  <li><a href="./">Navi03</a></li>
  <li><a href="./">Navi04</a></li>
  <li><a href="./">Navi05</a></li>
</ul>

で、これを seamless属性に対応していないブラウザで見ると…

seamless 属性の表示例。未対応ブラウザ

まぁ当然ですけどこうなります。iframe 内の要素には スタイルは継承されませんので、単純にプレーンな HTML が読み込まれて終了と。iframe 自体にも特にスタイルを当てていないので、枠線が表示されたりしています。青い背景がついているのは、親ドキュメントの方で、nav 要素に指定したスタイルが適用されているからです。

seamless 属性の表示例。未対応ブラウザ

さらにリンクをクリックしてみると… iframe 内でリンクが展開されますね。これは仕様通りの動作です。

お次に、seamless属性に対応した WebKit Nightly Builds で見てみると…

seamless 属性の表示例。対応ブラウザ

seamless 属性の表示例。対応ブラウザ

この通り、きちんと親ドキュメント上で指定したスタイルが iframe 内の要素にも継承されているのがわかります。また、リンクをクリックすると親ドキュメント上にリンクが展開されます。

別ドメインにあるファイルは対象外

ちなみに、同じ nav.html を今度は別のドメイン上に置いて、そこから読み込んでみるとどうなるかですが。下記のような感じになります。

seamless 属性の表示例。別ドメイン上のコンテンツを読み込み

枠線は消えていますが、スタイルの継承はされず、リンクもクリックすれば通常通り、iframe 内で展開されます。seamless 属性を有効にしたい場合は、iframe で読み込むコンテンツは同一ドメイン上に置きましょう。

なお、わかりやすいようにドメインで話をしていますが、厳密には同一オリジンをもつドキュメントが対象です。例えば親ドキュメントは http で表示していて、iframe で読み込むコンテンツが https で提供されているといった、スキームが異なる場合はオリジンが異なるので seamless 属性の指定が無視されます。細かいですが注意しましょう。

まとめ

ということで、例えば、サーバ側で SSI や PHP などが使えない、でも各ページで共通のパーツは外部ファイル化して読み込み、管理を楽にしたいななんて時 (今どきそんなシチュエーションがあるかは微妙ですが…)、seamless属性を使えば、iframe で同じようなことが簡単にできたりするかもしれません。あるいはタブで切り替える UI なんかにも応用できるかもしれませんね。

ちなみに、iframe を主要なナビゲーションやコンテンツに使うとか、アクセシビリティ的にどうなの?みたいな議論はあると思いますが、仕様上、「音声ブラウザは、seamless 属性が指定された iframe 内のコンテンツを別ドキュメントではなく、親ドキュメントと同一のものとして扱ってね」 と書かれています。つまり、音声ブラウザが対応していれば今よりも iframe がアクセシブルになるってことですが、広く対応するのがいつになるかはわかりませんのでその辺は微妙です。でも使い方によっては便利な属性になるかも。

関連エントリ

Recent Entry

全ての記事一覧を見る

Hot Entry

逆引きおすすめエントリー