frameは本当に便利か

フレームは実に多くの個人サイトで用いられています。 確かにメニューなどを固定すれば利便性が高まる時もあります。 しかしそれが絶対便利だと言い切れますか? どうせ使うなら正しく、デメリットも知った上で使ってみませんか? また、ここではフレームを他の技術で代替する方法も少し模索してみたいと思います。

このコンテンツの例文について

このコンテンツの例文は全てHTML4 Framesetの例です。XHTML 1.0 Framesetを利用している方は空要素等に注意を払う必要があります。また、例文中のhead要素に記述された内容は不足気味です。

フレームに関する様々な認識

フレームを使う方は大抵次のような理由で使っているようです。

また、フレームを使う事で 本来HTMLの内容としては不適なナビゲーションを本文中に書かなくて良くなります。 (文書の関連性を示すのはlink要素の役割です。 詳細は当サイトの「linkのススメ」をご覧下さい。) しかし、そのフレームには欠点も多くあります。 例えば次のような事です。

ナビゲーションリスト

現在W3Cで論議されているXHTML2.0にはnl要素型というナビゲーションの為のリスト(Navigation List)が導入されるかもしれません。 そうなれば多少話は変わってくるでしょう。 (個人的にはこの要素型自体がおかしいように思いますが。)

フレームを用いたままで改善しようと試みる

すべてのページにナビゲーションを入れる

勿論「ナビゲーション部を1つのファイルで共有できるので維持が楽」というメリットがあるのは前述した通りです。 ここで追加するのはそんな立派なナビゲーションではありません。 「トップページ」へのリンクと「メニュー」へのリンクです。 「メニュー」はフレームに読み込む物と兼用にしても良いでしょう。

トップページへのリンクがあれば、偶々「フレームに読み込まれるはずのページ」に来た訪問者をトップページ(すなわちフレーム付きの文書)に誘導する事が出来ます。 また、メニューへのリンクがあればフレームに対応していないブラウザでも(少々不便とはいえ)閲覧する事ができます。

このように改善しても結局リンクはしにくいままです。 しかし不便さを最小限に抑える事は出来るでしょう。

noframes要素は重要だ

さて、この要素きちんと使っていますか? 「そもそもフレームに対応していない時代遅れな(?)ブラウザを使ってる奴が悪いんだ」なんて言ってはいけません。 大半の検索エンジンは要約文を提供しています。 閲覧者はその要約文からそのページが自分にとって有用かを判断するでしょう。 が、noframes要素に「フレーム対応ブラウザでご覧下さい。」などと書かれていると全く参考にならない文になってしまいます。 試しにいくつかの検索エンジンの要約文を見てみましょう。

一部の検索エンジンを除いて要約文が「フレーム対応の……」といった具合の参考にならない文になってしまっています。 きちんとnoframes要素の中に 代わりになる文 を書けばこうはなりません。 例えば次のような文書があったとします。

ありがちなframeの使われ方
<p><!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Frameset//EN” “<a href="http://www.w3.org/TR/html4/frameset.dtd">">http://www.w3.org/TR/html4/frameset.dtd"></a>
<html>
<head><title>なんとかかんとかのページ</title></head>
<frameset cols="150,*">
  <frame src="menu.html" name="left">
  <frame src="main1.html" name="right">
</frameset>
<noframe>このページはフレームを使用しています。フレーム対応ブラウザでご覧下さい。</noframe>
</html></p>

このような記述は非常に多くのサイトで見られます。 この記述には基本的な文法事項に2つ間違いがあります。 まず、 noframes要素はframeset要素の直下に記述する ものです。 しばしば先程の例のようにhtml要素の直下に書かれますが、これは間違いです。

もう1つはnoframeではなくnoframes要素だと言う事。 複数に分けられたウィンドウの代替ですから noframesは複数形 です。 これら2つはよく間違われますので気をつけましょう。

では本題のnoframes要素を見てみましょう。 多くのサイトにはこの様に「追い返す」為の文が書かれています。 果たして追い返すべきなのでしょうか。 次のようにmenu.htmlへのリンクを準備するだけで、そのリンクとUAの持つ「戻る」機能を駆使する事で閲覧者は情報を得る事が出来ます。

先程の例を少し改善した例
<p><!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Frameset//EN” “<a href="http://www.w3.org/TR/html4/frameset.dtd">">http://www.w3.org/TR/html4/frameset.dtd"></a>
<html>
<head><title>なんとかかんとかのページ</title></head>
<frameset cols="150,*">
  <frame src="menu.html" name="left">
  <frame src="main1.html" name="right">
  <noframes>
    <body>
      <h1>なんとかかんとかのページ</h1>
      <ul>
        <li><a href="menu.html">サイトメニュー</a></li>
        <li><a href="main1.html">トップページ</a></li>
      </ul>
    </body>
  </noframes>
</frameset>
</html></p>

noframes要素の中にはフレームとして読み込むページへのリンクを記述する のが普通です。 そうすれば一応全てのページへアクセスする事ができますからね。

尚、「フレーム対応ブラウザの紹介」をnoframes要素の中に書いているサイトを見かけますが、既に時代遅れでしょう。 紹介された物を使ってまでそのサイトにアクセスしようと思う人は少ないでしょうし、そもそもその紹介された物を使いたくても使う事ができないのかもしれません。

もう1つのnoframes要素

noframes要素には2つの種類があります。 当サイトの「ブロック要素とインライン要素の違い」での説明を以下に引用します。 (実のところ解決方法はこの中に簡潔にまとめられています。)

要素名 説明
noframes (Frameset) frameに非対応のUAに対して表示するテキストです。HTML4 FramesetとXHTML 1.0 Framesetでのみ定義されています。この要素は frameset要素の直下 に含みます。html要素の直下に書いている人を見かけますが、間違いです。また、Transitionalで定義されているnoframes要素とは根本的に異なるものです。適宜そちらも参照してください。この要素の中には丸ごと 一つの文書が記述されます 。(勿論noframes要素を含むことは出来ませんが。)しばしば「フレーム対応ブラウザでご覧下さい」などと書かれますが、好ましくありません。まして「フレーム対応ブラウザはこちらから入手してください」なんて書いてあったら最悪です。(そんなことは知っていて使っている可能性が高いですから>。)面倒かもしれませんが、きちんと代替文書となりうるテキストを含めましょう。もしメニューフレームが存在するならとりあえずメニューとなりうるリン>クを羅列しておくのがいいと思います。そして各ページにもTransitionalで定義されているnoframes要素を用いてメニューを書いておけば>完璧です。
noframes ここではTransitionalで定義されているnoframes要素を解説します。決してnoframeではありません、 複数形 で>す。これはフレームが無効だった場合に表示される 代替文書 です。この中身はフレームに非対応のUAがフレーム内部に使われているページを直接表示した際に表示されます。Framesetで定義されるnoframes要素も参照してください。(一般によく使われるのはFramesetに定義されるnoframes要素です。) この要素はbody要素の直下にのみ含まれます。フレームに記載した他コンテンツへのリンクを記述するのが良いでしょう。

要するに先ほど説明したnoframes要素というのはFramesetで定義されるnoframes要素と言う事になります。 ここではTransitionalで定義されるnoframes要素について解説します。

このTransitionalで定義されるnoframes要素は frame非対応の環境だけに有して欲しい情報を記述する際に使います 。 例えば次のようにナビゲーションに用いる事が考えられます。

noframes要素でナビゲーションを括る例
<p><body>
  <h1>ページのタイトル</h1>
  <p>このページのメインコンテンツな部分</p>
  <noframes>
    <p><a href="menu.html">メニュー</a>へ戻る</p>
  </noframes>
</body></p>

しかし前述の通り、偶々「フレームに読み込まれるはずのページ」に来た訪問者にもナビゲーションを提供する必要があります。 トップページへのリンクは最低限でも準備しなくてはならないでしょう。それを踏まえてもう一度書き直してみます。

先ほどの例をもう一歩進めた例
<p><body>
  <h1>ページのタイトル</h1>
  <p>このページのメインコンテンツな部分</p>
  <noframes>
    <p><a href="menu.html">メニュー</a>へ戻る</p>
  </noframes>
  <p><a href="index.html" target="_top">トップページへ戻る</a></p>
</body></p>

この様にしておけば行き止まりはなくなりますし、一応誰でもリンクを辿れば見る事の出来るサイトになります。 但し トップへ戻るリンクにはtarget属性を指定しないと痛い目に遭います

今までの事をよく整理してみましょう

通常のページに「トップページ」と「メニュー」へのリンクが追加すると良い…という話でした。 しかしよく考えてみて下さい。 「メニュー」のリンクを使う(すなわちフレームが無効となる環境の)閲覧者が「トップページ」へのリンクを使うと「メニュー」へ誘導するメッセージが表示されます。 …ということは「トップページ」に「メニュー」を書いてしまえばそもそもTransitionalで定義されるnoframesは不要になるのです。 以下にその例を示します。

理想に近いframeの例
<p><!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Frameset//EN” “<a href="http://www.w3.org/TR/html4/frameset.dtd">">http://www.w3.org/TR/html4/frameset.dtd"></a>
<html>
<head><title>なんとかかんとかのページ</title></head>
<frameset cols="150,*">
  <frame src="menu.html" name="left">
  <frame src="top.html" name="right">
  <noframes>
    <body>
      <!– 以下の内容はmenu.htmlに記述されている内容だと仮定して下さい –>
      <h1>なんとかかんとかのページ Contents</h1>
      <ul>
        <li><a href="aaa.html">1つめのコンテンツ</a></li>
        <li><a href="bbb.html">続きまして2つめのコンテンツなり</a></li>
        <li><a href="bbs.cgi">掲示板</a>で話しませんか</li>
        <li><a href="about.html">このページについて</a></li>
      </ul>
      <!– top.htmlに記述されている内容も記入しましょう –>
    </body>
  </noframes>
</frameset>
</html></p>

「メニュー」を2ヶ所に記述する事になり若干フレームを使うメリットは減ってしまいますが、それ以上の価値があるでしょう。 (他の技術に頼ればフレーム同様に1つのファイルで共有できます。)

適切な属性値を指定する

ここでポイントとなるのは *frame要素のname属性とtitle属性* です。 例えばホームページ・リーダー(v2.5)はtitle属性の値を参照して読み上げるそうです。 また、Lynxなどはname属性の値をフレームとして読み込むファイルへのリンク文字列として利用します。 もしかしたら貴方の携帯電話もそう処理してくれるかもしれません。 (僕の携帯電話(J-T010)はそういった処理を行ってくれます。)

従ってtitle要素とname要素には一見して内容が分かるような値を持たせる必要があります。 これを元に今までに挙げた例を改善してみましょう。

理想的なframeの例
<p><!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Frameset//EN” “<a href="http://www.w3.org/TR/html4/frameset.dtd">">http://www.w3.org/TR/html4/frameset.dtd"></a>
<html>
<head><title>なんとかかんとかのページ</title></head>
<frameset cols="150,*">
  <frame src="menu.html" title="メニュー" name="menu">
  <frame src="top.html" title="メインコンテンツ" name="main">
  <noframes>
    <body>
      <!– 以下の内容はmenu.htmlに記述されている内容だと仮定して下さい –>
      <h1>なんとかかんとかのページ Contents</h1>
      <ul>
        <li><a href="aaa.html">1つめのコンテンツ</a></li>
        <li><a href="bbb.html">続きまして2つめのコンテンツなり</a></li>
        <li><a href="bbs.cgi">掲示板</a>で話しませんか</li>
        <li><a href="about.html">このページについて</a></li>
      </ul>
      <!– top.htmlに記述されている内容も記入しましょう –>
    </body>
  </noframes>
</frameset>
</html></p>
name属性について

name属性の値はアルファベットで始まらなくてはなりません(数字で始める事はできません)。 また、XHTML 1.0に於いてname属性は非推奨とされ、id属性の利用が推奨されています。 XHTML 1.0 Framesetに準じて記述する場合はname属性とid属性を併記するのが好ましいでしょう。

longdesc属性

frame要素にはそのフレームの説明を記述した文書と関連づける為にlongdesc属性が準備されています。 タイトルで伝えきれない情報をlongdesc属性を用いて関連づけましょう。 尚、longdesc属性の値はフレーム枠の説明を記述した文書のURIです。

画面幅は可変にする

frame要素にはnoresizeという属性が準備されています。 これを指定する事によってフレームの幅を変えられなくする事が出来るのです。 しかし、その固定した幅が閲覧者にとって理想的とは限りません。 閲覧者の画面幅なんて製作者は知り得ないのです。

もしかしたら重要でないフレームが画面を占拠してしまい、もう1つの重要なフレームが凄く細くなってしまっているかもしれません。 そんな時、幅を変えられないのは不便だと思いませんか?

フレームの中身までURIで指定する事ができない

これこそがフレームの最も致命的な問題です。 現在草案段階のXFramesではhttp://example.org/home.frm#frames(id1=uri1,id2=uri2,...)といったURIになる予定ですからこの問題は解決する事になります。 URIでフレームの中身まで指定したいのは山々ですが、それはXFramesが実用化されるまで待つ事にしましょう。 だいぶ先の話になるでしょうが…。

W3Cの側面から見るフレームの存在

そもそもframeはNetscapeの独自拡張規格を取り入れた規格であった為、HTML本来の「マークアップ」になっていません。 そのため、フレームはHTML4 FramesetとXHTML 1.0 Framesetだけに定義され、XHTML1.1では定義されませんでした。 そして今論議されているXHTML2.0にはXFramesが取り込まれる予定です。

他の技術へ切り替える

スタイルシートを使うことで表示場所を固定する事ができます。 その為には全ての場所に「メニュー」を記述する必要があります。 (全てのページにメニューを記述するならフレームを用いる必要がない事は明らかです。)

面倒は嫌いだという人の為のちょっとしたヒント

SSIなどの技術を使えば、全てのファイルに同じメニューを組み込む事は簡単です。 このサイトでも似たような事が行われています。 ……そう、実は{{ナビゲーション部を1つのファイルで共有する事は別にフレームを使わなくても可能なのです。

CSSでposition:fixedを使ってしまう方法が分かりやすいのですが、MSIE6が対応していないという致命的な欠点があります。 その為、overflowプロパティを使うのが妥当です。 詳細な方法は以下のサイトを参照して下さい。