framesetタグの正しい使い方とよくある間違い

framesetタグは、1つのブラウザー画面を複数の領域に分割し、それぞれに別のHTML文書を表示するための仕組みです。かつては、左側にメニュー、右側に本文を置く構成や、上部にタイトル、下部にコンテンツを表示する構成で広く使われていました。現在はHTML5で廃止された古い仕様ですが、レガシーサイトの保守や移行作業では、仕組みを正しく理解しておく必要があります。

特に古い日本語サイトでは、フレーム分割そのものに加えて、文字コードの不一致、相対パスの誤り、リンク先の表示領域指定ミスなどが重なりやすい傾向があります。framesetとframeの役割を区別し、表示の仕組みと問題の切り分け方を押さえることが、修正の第一歩になります。

framesetタグの役割と基本構造

framesetタグは、ブラウザーの表示領域を行方向または列方向に分割します。横方向に分ける場合はrows属性、縦方向に分ける場合はcols属性を使います。例えば、左側を幅200ピクセルのメニュー、右側を残りの領域にするなら、次のように記述します。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
  "http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
  <title>フレーム構成</title>
</head>
<frameset cols="200,*">
  <frame src="menu.html" name="menu">
  <frame src="main.html" name="main">
</frameset>
</html>

ここで重要なのは、framesetを通常のbody要素の中に書かないことです。フレームセット文書では、基本的にbodyの代わりにframesetを置きます。bodyとframesetを同じ階層で併記すると、ブラウザーや検証ツールによって解釈が不安定になり、意図した分割が行われない場合があります。

frameは、分割された各領域に読み込むHTMLファイルを指定する要素です。src属性が読み込み先、name属性がリンクの表示先を識別する名前になります。フレームそのものに文章を書くのではなく、内容は別ファイルに分けて管理する点が、通常のHTMLレイアウトと大きく異なります。

rows属性とcols属性の指定方法

rows属性は上下分割、cols属性は左右分割を指定します。値はカンマ区切りで記述し、ピクセル値、割合、残りを表すアスタリスクを組み合わせられます。例えば、rows="100,*,80"なら、上部を100ピクセル、下部を80ピクセルに固定し、中央を残りの高さにします。

<frameset rows="100,*,80">
  <frame src="header.html" name="header">
  <frame src="content.html" name="content">
  <frame src="footer.html" name="footer">
</frameset>

割合による指定も可能です。cols="25%,75%"と書けば、画面幅をおおむね4分の1と4分の3に分割できます。ただし、固定値と割合を混在させた場合の計算結果は、ブラウザーの表示幅や仕様解釈に左右されることがあります。可変領域を明確にしたい場合は、*を使って余った空間を割り当てる方法が扱いやすいでしょう。

分割をさらに入れ子にする場合は、frameの代わりに内側のframesetを置きます。例えば、上部にヘッダーを固定し、下部をメニューと本文に分ける構造は次の形です。

<frameset rows="90,*">
  <frame src="header.html" name="header">
  <frameset cols="220,*">
    <frame src="menu.html" name="menu">
    <frame src="main.html" name="main">
  </frameset>
</frameset>

frame要素とリンク先の関係

メニューから本文フレームへページを表示するには、リンクのtarget属性に、表示したいframeのnameを指定します。本文領域にmain.htmlを表示したいなら、メニュー側は次のようになります。

<a href="news.html" target="main">ニュース</a>
<a href="profile.html" target="main">プロフィール</a>

このとき、target="main"の値と、フレーム側のname="main"が完全に一致していなければなりません。大文字と小文字の違い、余分な空白、名前の変更漏れがあると、リンク先が新しいウィンドウで開いたり、現在の領域を置き換えたりします。

よくある誤りは、idだけを設定してnameを省略することです。現代のHTMLでは要素識別にidを使う場面が多いものの、古いフレームのリンク先指定ではnameが基本になります。保守時には、リンクのtarget、読み込み側のname、実際のファイル名を一組として確認してください。

特殊なターゲット名にも注意が必要です。_selfは現在のフレーム、_parentは親フレーム、_topはフレーム構造全体、_blankは新しいウィンドウやタブを意味します。誤って_topを指定すると、メニューを含む全体がリンク先へ置き換わります。意図的な指定かどうかを確認し、サイト全体の操作性に影響するリンクを優先して点検します。

スクロールやサイズを制御する属性

古いフレームサイトでは、scrolling、noresize、frameborder、marginwidth、marginheightなどの属性がよく使われます。scrolling="yes"ならスクロールバーを表示し、scrolling="no"なら表示を抑制します。scrolling="auto"は必要に応じて表示する指定です。

<frame src="menu.html"
       name="menu"
       scrolling="auto"
       frameborder="0"
       marginwidth="8"
       marginheight="8">

noresizeを付けると、利用者がフレーム境界をドラッグしてサイズを変更できなくなります。デザインを固定しやすい反面、狭い画面で本文が読みにくくなったり、メニュー幅を広げられなくなったりします。固定が必要な理由がなければ、利用者による調整を妨げないほうが実用的です。

frameborderの表示結果はブラウザーによって差が出ることがあります。また、フレームの内側余白を小さくしすぎると、文字や画像が端に接して読みにくくなります。古いサイトを再現する場合でも、見た目だけを優先してスクロールを禁止すると、長い文章や大きな画像が切れるため、各フレームの内容量を確認して値を決める必要があります。

noframesとアクセシビリティへの配慮

noframes要素は、フレームに対応していないブラウザーや、フレームを利用できない環境向けの代替内容を置くために使われます。短い説明だけで済ませず、主要ページへのリンクやサイトの目的を記述すると、閲覧できる情報が増えます。

<noframes>
  <body>
    <p>このサイトはフレームを使用しています。</p>
    <p><a href="main.html">本文ページへ移動</a></p>
  </body>
</noframes>

ただし、noframesを用意しただけでアクセシビリティ上の問題が解消するわけではありません。スクリーンリーダー、検索エンジン、スマートフォンの小さな画面では、フレーム構造が理解しにくいことがあります。各コンテンツが独立したURLを持つため、本文だけを開いた利用者にはメニューやサイト名が表示されない場合もあります。

ページタイトル、見出し、代替テキスト、キーボード操作への対応も確認すべき項目です。フレームをすぐに置き換えられない保守案件では、noframesにサイトマップを置き、各本文ページからトップページやナビゲーションへ戻れるリンクを加えるだけでも、利用上の不便を減らせます。

文字コードとファイルパスの間違い

日本語が「文字化け」している場合、frameset自体の構文ではなく、親ページと子ページの文字コードが一致していない可能性があります。HTMLファイルがShift_JISで保存されているのに、meta要素でUTF-8を宣言している、あるいはサーバーのHTTPヘッダーが別の文字コードを返しているケースが代表的です。

古いページを修正する際は、ファイルの実際の保存形式、HTML内の文字コード宣言、サーバー設定のContent-Typeを順番に確認します。ブラウザーのエンコード表示だけを変更して一時的に読めても、リンク先の子フレームが異なる設定なら再び崩れます。原因の切り分けには、文字化けの修復手順も参考になります。

ファイルパスの誤りも頻出します。src="main.html"は、フレームセットHTMLと同じ階層にあるファイルを指します。子ディレクトリならsrc="pages/main.html"、一つ上の階層ならsrc="../main.html"です。サーバー上のURLとローカル環境のパスを混同すると、トップページでは枠だけ表示され、内部に「ページが見つかりません」と出る状態になります。

画像やCSSの相対パスは、フレームセット文書ではなく、読み込まれる子HTMLファイルを基準に解決されます。例えばpages/main.html内の画像をimages/logo.gifと指定した場合、通常はpages/images/logo.gifが探されます。実際の配置が別階層なら、子ページから見た正しい相対パスに直さなければなりません。

HTML5時代の移行と代替方法

frameset、frame、noframesはHTML5で廃止された要素です。新規サイトでフレーム構造を採用すると、文書検証、検索性、レスポンシブ対応、支援技術との互換性で不利になります。現代のページでは、通常のbody内に意味のあるHTMLを配置し、CSSのFlexboxやGridで画面を分割する方法が基本です。

例えば、メニューと本文を左右に並べるだけなら、次のような構造にできます。

<body>
  <div class="layout">
    <nav>
      <a href="news.html">ニュース</a>
      <a href="profile.html">プロフィール</a>
    </nav>
    <main>
      <h1>サイトの本文</h1>
      <p>ページの内容をここに記載します。</p>
    </main>
  </div>
</body>
.layout {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  gap: 24px;
}

この方法なら、ナビゲーションと本文が同じ文書構造に含まれ、検索エンジンや支援技術が内容を把握しやすくなります。画面幅が狭い場合はメディアクエリで1列に変更でき、スマートフォンにも対応できます。ページ全体を共通化したい場合は、サーバーサイドインクルード、テンプレートエンジン、CMSなどを使う選択肢もあります。

ただし、既存サイトを一度に全面移行する必要はありません。まずリンク切れ、文字化け、タイトル不足、直接アクセス時の戻り先不足を直し、次に共通ナビゲーションを通常のHTMLへ移し、最後にURL構造を保ちながら段階的にフレームを廃止する流れが現実的です。

よくある失敗を点検する方法

最初に確認するのは、DOCTYPEとルート構造です。フレームセット用のDOCTYPEが必要な古い文書なのか、HTML5として書かれているのかを見分けます。HTML5のDOCTYPEでframesetを使っている場合、仕様上の問題を抱えたまま動作している可能性があります。

次に、次の項目を一つずつ確認します。

ブラウザーの開発者ツールでは、ネットワークエラー、404エラー、文字コード、読み込み順序を確認できます。画面全体が白い場合は構文やDOCTYPE、枠だけ表示される場合はsrcやパス、リンクを押したときだけ問題が起きる場合はtargetを疑うと、原因を絞り込みやすくなります。

修正後は、トップページからの操作だけでなく、各子ページへの直接アクセスも試してください。ブックマークや検索結果から本文ページを開いた利用者が、サイトの構造を失わずに移動できるかを確認します。古いフレームサイトでは、見た目が再現できても情報への到達性が損なわれていることがあるため、表示確認と利用確認を分けて行うことが大切です。

既存のフレームサイトを保守する場合は、まずframeset、frame、target、文字コード、相対パスを順に点検し、問題箇所を小さく切り分けてください。新しく構築する場合は、CSSレイアウトと意味的なHTMLを選び、古い構造は段階的に置き換えるのが安全です。必要なページを洗い出し、リンク切れと文字化けを修正するところから、サイトの再利用と移行を始めましょう。