[ SPECIAL ]

HTML

フレームやテーブルを使わずに表示領域を分割する

2005/09/08 Tomohiro Kumagai
Update: 2005/09/25 Tomohiro Kumagai

□ 理想としては、コンテンツを左に、メニューを右に…

HTML にて表示領域を分割するには、いろいろな方法があります。

簡単なのがフレームを用いる方法ですけど、これは複数の HTML ファイルで構成するため、自動巡回型の検索サイトからの訪問も想定した場合にはメニューがなくなってしまうなどの不都合が出てきます。

 

そこで個人的に、ひとつの HTML ファイルにテーブルを用いて領域を分割してみていたのですけど、それだと条件によってはテーブルの準備が終わるまでページが表示されないという場合があるようでした。

全体の読み込み時間が早いようなら良いのですけど、そうでない場合に待たないといけないのは何かと都合が悪いので、何か別の方法で、DIV タグや SPAN タグを駆使して領域を分割できないか調べてみることにしました。

 

ともあれまずは、これまでに試してきた "フレーム" や "テーブル" を使った場合のお話しです。

 

フレームを用いて表示領域を分割する

基本となる HTML ファイルに加えて、今回の例では "CONTENTS.html" と "MENU.html" という、合計 3 つの HTML ファイルを用意して、それをまとめて表示します。

<html>

<head>

<title></title>

</head>

 

<!-- フレーム領域の定義 -->

<frameset cols="*,200">

 

<!-- コンテンツ表示用の領域 -->

<frame name="contents" src="CONTENTS.html">

 

<!-- メニュー表示用の領域 -->

<frame name="menu" src="MENU.html" target="menu">

 

<!-- フレーム未対応だった場合に表示される部分 -->

<noframes>

<body>

</body>

</noframes>

 

</frameset>

 

</html>

非常に手軽で判りやすい方法ですし、何よりどのブラウザでも想定どおりに見えることが多いので便利なのですけど、フレーム構成でページを表示させるためには基本となる HTML ファイルからアクセスしないといけないのが難点です。

 

普通は問題ないのですけど、たとえば自動巡回型の検索サイトからたどり着いたような場合だと、時にたとえば "CONTENTS.html" ファイルから表示しようとするため、そうするとメニューが抜けてしまったりすることがあります。

そういった自動収集による検索サイトを利用してのアクセスアップを考慮している場合には、フレームは少し適さないような感じがします。

 

テーブルを用いて表示領域を分割する

テーブルというのは、HTML ファイルの中に表を描くためのもので、それをうまく調整することで、コンテンツ領域とメニュー領域を分割することも可能です。

<html>

<head>

<title></title>

</head>

 

<!-- テーブル構成の開始 -->

<table width="100%" height="100%">

<tr>

<!-- コンテンツ表示用のセル -->

<td valign="top">

---- コンテンツデータをここへ記載します ----

</td>

 

<!-- メニュー表示用のセル -->

<td valign="top" width="200">

---- メニューデータをここへ記載します ----

</td>

 

</tr>

</table>

 

</html>

画面いっぱい ( width="100%" height="100%" ) のテーブルを用意して、必要な領域に幅 ( width="200" ) を指定します。また、そのままだと文字が縦中央に寄せられてしまうようなので、それぞれにて上から表示されるように ( valign="top" ) 設定します。

ひとつの HTML ファイルで構成されるため、それぞれのページに対してメニューの HTML も書き込まないといけませんけど、こちらもほとんどのブラウザで想定どおりに見えるでしょうし、フレームと違って自動巡回型の検索サイトからの訪問でもメニューがなくなるような心配がないので安心です。

 

フレームと異なる点としては、両方合わせて 1 つのスクロールバーとなるというところでしょうか。テーブルで一画面をオーバーした場合、フレームと違ってスクロールバーが全体にたいして用意されるので、コンテンツ領域とメニュー領域が一緒にスクロールするような感じになります。

また、長い画像を配置したりして横幅がオーバーしたりすると、右側のセルが外に押しやられてしまう可能性もあります。その場合は TABLE タグにスタイルシートを用いて "table-layout: fixed" を指定してあげることで、フレームのようにしっかりと領域を固定することが出来るようになります。

 

もしテーブルのように溢れた方にのみスクロールバーを表示したいような場合は、DIV タグとスタイルシートを利用すれば実現可能です。ただし、対応していないブラウザも少しは出てくる可能性がありますので気をつけましょう。

<html>

<head>

<title></title>

</head>

 

<!-- テーブル構成の開始 -->

<table width="100%" height="100%">

<tr>

<!-- コンテンツ表示用のセル -->

<td valign="top">

<div style="height: 100%; overflow: auto">

---- コンテンツデータをここへ記載します ----

</div>

</td>

 

<!-- メニュー表示用のセル -->

<td valign="top" width="200">

<div style="height: 100%; overflow: auto">

---- メニューデータをここへ記載します ----

</div>

</td>

 

</tr>

</table>

 

</html>

テーブル内のセルに、さらに DIV タグを用意して、そこにスタイルシートを用いてスクロールバーを必要に応じて表示するように ( overflow: auto" ) 設定します。

このとき合わせて、DIV タグがセルの縦幅いっぱいに広がるように幅を設定する ( height: 100% ) ことも忘れないようにします。これはどうやらタグでの幅指定ではダメなようですので、必ずスタイルシートで設定しましょう。

 

ただこのテーブルを使った方法は、ブラウザにも依るのかも知れないですけど、テーブルの中のセル全体の準備が整ってから表示されるということもあるようなので、どこかのセル内で表示が遅かったりすると、全体的な表示が遅れてしまうこともあるようです。

これについても "table-layout: fixed" を指定することで幾分緩和されるようなことを聞いたことがありますので、テーブルによる領域分割を行う場合には、この設定をして置くのが良さそうな気がします。

 

□ SPAN で分割し、JavaScript で整える

お勧めできる方法ではないですけど、まずは DIV タグを用いてなんとか分割できないかと試行錯誤したお話しから。

SPAN を用いて分割する

SPAN タグは幅を指定することが出来るので、それを用いて領域を左右に分割することは出来ます。

<span style="width: 400px">

---- コンテンツデータをここへ記載します ----

</span>

 

<span style="width: 200px">

---- メニューデータをここへ記載します ----

</span>

ただし、この場合は 400px + 200px の固定された領域になってしまいます。でも、個人的にはウィンドウいっぱいに表示したいのでした。だからと言って次のようにしてしまうと、メニュー領域が下へ折り返されてしまいます。

<span style="width: 100%">

---- コンテンツデータをここへ記載します ----

</span>

 

<!-- この部分が次の行へ折り返されてしまう -->

<span style="width: 200px">

---- メニューデータをここへ記載します ----

</span>

 

JavaScript を用いて調整する

そこで、あれこれ考えた末に思いついたのが、JavaScript を用いてメニュー領域の位置を調整する方法でした。

SPAN タグは、スタイルシートを用いて自由な位置へ配置することが出来ますので、それを利用してコンテンツ領域の端っこにメニュー領域を持って来ようという作戦です。そのとき、メニューの配置位置を JavaScript を用いて計算します。

 

いろいろと複雑になってしまうので、今回は SPAN に class 属性を設定してスタイルシートの値を適用します。

ともあれまずは、コンテンツ領域とメニュー領域に使用する SPAN タグを記載した HTML を用意します。その際に JavaScript で操作しやすくするために、それぞれに "contents_field" と "menu_field" という ID を設定しておきます。

<!-- コンテンツ表示用の領域 -->

<span id="contents_field" class="contents_style">

---- コンテンツデータをここへ記載します ----

</span>

 

<!-- メニュー表示用の領域 -->

<span id="menu_field" class="menu_style">

---- メニューデータをここへ記載します ----

</span>

そして、それぞれの領域のためのスタイルを定義します。

<!-- コンテンツ領域用のスタイル -->

.contents_style

{

width: 100%;

height: 100%;

overflow: auto;

 

margin-top: 0px;

margin-bottom: 0px;

margin-left: 0px;

margin-right: 200px;

 

padding: 0px;

}

 

<!-- メニュー領域用のスタイル -->

.menu_style

{

width: 200px;

height: 100%;

overflow: auto;

 

margin: 0px;

padding: 0px;

}

メニュー領域は固定 ( width: 200px ) にして、コンテンツ領域の方では、幅を最大 ( width: 100% ) にした上で、メニュー領域を配置するための余白 ( margin-right: 200px ) を設定しています。また、どちらのフィールドとも、表示領域を溢れたときには自動的にスクロールバーが表示されるように ( overflow: auto ) しています。

 

そして、メニュー領域を動かすために、次のような JavaScript を用意します。

// 調整しやすくするために、メニュー領域の幅を設定しておきます。

var MENU_WIDTH = 200;

 

 

//////////////////////////////////////////////

// HTML が読み込み終わった後に呼び出す関数です。

//

function initialize()

{

// メニューの位置をウィンドウに合わせて調整します。

SetMenuPosition(menu_field);

}

 

//////////////////////////////////////////////

// メニュー領域の位置を調整します。

//

function SetMenuPosition(objMenu)

{

// メニューの位置指定を "絶対位置指定" とします。

objMenu.style.position = 'absolute';

 

// 表示位置を天辺の右端にします。

objMenu.style.top = 0;

objMenu.style.left = GetBodyWidth() - MENU_WIDTH;

}

 

//////////////////////////////////////////////

// 表示領域全体の横幅を取得する関数です。

//

function GetBodyWidth()

{

var result;

 

// document.all や document.layers の存在で、ブラウザを判定できるようです。

if (document.all)

{

// Internet Explorer 系だった場合の横幅取得です。

result = document.body.clientWidth;

}

else if (document.layers)

{

// Netscape 系だった場合の横幅取得です。

result = innerWidth;

}

else

{

// 想定外はとりあえず -1 としておきました。

result = -1;

}

 

return result;

}

 

あとは、この関数を HTML が読み終わった後に実行されるように、BODY タグを調整します。

<body onload="initialize()" onresize="SetMenuPosition(menu_field)">

HTML の読み込みが終了すると "onload" 属性に指定されたスクリプトが実行されるので、ここで "initialize()" 関数を呼び出してメニュー領域をコンテンツ領域の右余白へ移動します。また、ウィンドウサイズが変更された場合にも対応できるように、同様に "onrisize" 属性にも、メニュー領域の位置を調整するための関数を設定しておきます。

 

これで、領域の分割は完成です。ただ、JavaScript を用いていわゆる Dynamic HTML を使用する場合は特に、ブラウザ毎に見栄えに大きな違いが現れる可能性がありますので注意が必要です。

Windows の Internet Explorer 6.0 では大丈夫でしたけど、Macintosh の Internet Explorer 5.2 で動かしてみると、レイアウトは正しいものの、スクロールバーが余白にまで伸びるために、その一部がメニュー領域の下に隠れてしまう感じでした。

また Macintosh の Safari 2.0.1 でも、メニュー領域が正常には表示されてくれませんでした。この原因は、上記の JavaScript の GetBodyWidth() 関数が問題のようです。Safari では "document.all" や "document.layers" による条件判定が出来ないみたいで、該当しなかったときの -1 が返ってしまうのが原因でした。

safari の場合は Internet Explorer と同様に document.body.clientWidth の値を参照することでウィンドウの幅を取得することが出来るようでしたけど、ともあれ safari の場合、という判定スクリプトを組み込んだりしないといけません。

 

他の環境にも影響される可能性もありますので、この方法はとりあえず出来たという感じでした。

 

□ DIV だけで分割する

JavaScript を用いた方法だと、とても対応ブラウザの想定が難しく、また、非対応だった場合の影響が非常に大きい…。

そんな感じで何か別の方法がないものかと思っていたら、書店で眺めていたスタイルシートの本の中で "float" という指定が出来ることがわかりました。これはたとえば IMG タグに ALIGN を指定したときの様な感じで、オブジェクトを指定した位置に回りこんで表示させることができると言うものでした。

実のところ、そういう風に簡単に出来たらなって思っていたところだったので、さっそく試してみました。

 

SPAN タグだけで分割してみる…

まずは SPAN タグを用いて分割を行ってみました。

フローティングの設定ですので、それを指定するのは幅の決まったメニュー領域に、そしてコンテンツ領域よりも先に表示させます。そのようなことに注意して、とりあえず HTML は次のような感じになりました。レイアウトはスタイルシートで行います。

<!-- メニュー表示用の領域 -->

<span class="menu_style">

---- メニューデータをここへ記載します ----

</span>

 

<!-- コンテンツ表示用の領域 -->

<span class="contents_style">

---- コンテンツデータをここへ記載します ----

</span>

そして、スタイルシートの設定です。

<!-- コンテンツ領域用のスタイル -->

.contents_style

{

width: 100%;

height: 100%;

overflow: auto;

}

 

<!-- メニュー領域用のスタイル -->

.menu_style

{

width: 200px;

height: 100%;

overflow: auto;

 

float: right;

}

コンテンツ領域は可能な限りの幅 ( width: 100%; height: 100% ) に広げて、メニュー領域の方は適切な幅 ( width: 200px; height: 100% ) に制限します。そしてメニュー領域の配置として、右寄せ ( float: right ) を指定します。

 

こうしてみたところ、Windows の Internet Explorer 6.0 では、コンテンツ領域が画面いっぱいを占めてしまってメニュー領域が見えませんでした。ウィンドウの大きさを調整しなおすと、何事もなかったかのように分割表示されるのですけど…。他にも Macintosh の Internet Explorer 5.2 では、コンテンツ領域が次の行へ送られてしまいました。

Macintosh の Safari 2.0 では、コンテンツ領域の背景色を SPAN へそのままスタイルシートで指定できないものの、レイアウト的には期待通りの、画面いっぱいを表示領域とした上で右側にメニューが表示されるようでしたけど。

 

DIV タグを織り交ぜてみる

折り返されてしまったり、メニュー領域が追いやられてしまうのは、横幅の問題。

SPAN タグを最大限に広げるために width: 100% を指定している訳ですけど、これがきっと影響してしまっているのでしょう。かといってこれを指定しないと SPAN の性質上、必要最小限の横幅に自動的に調整されてしまいます。

 

それならばコンテンツ領域の方を DIV に変えたら良いのではないかと思って、試してみることにしました。

<!-- メニュー表示用の領域 -->

<span class="menu_style">

---- メニューデータをここへ記載します ----

</span>

 

<!-- コンテンツ表示用の領域 -->

<div class="contents_style">

---- コンテンツデータをここへ記載します ----

</div>

DIV は SPAN と違って、自動的に必要最大限の横幅を取ります。ですので、特に幅を指定しなくても、メニュー領域が右にフローティングされた時点での最大限の幅を取ってくれるのではないかと思います。

そのような都合で幅をブラウザ側で自動調整してもらうために、コンテンツフィールド用のスタイルシートから明示的な幅指定である width の行を取り除いておきます。メニュー領域の方はそのままです。

<!-- コンテンツ領域用のスタイル -->

.contents_style

{

height: 100%;

overflow: auto;

}

このようにしてみたところ、Windows XP の Internet Explorer 6.0 はまさに理想どおりに、Macintosh の Internet Explorer 5.2 も Safari 2.0 も、期待通りの領域分割を行うことができました。

ただし Macintosh の Internet Explorer 5.2 だと、スクロールバーの表示がなされてしまうことと、その挙動も、マウスのホイールでは動かせないなど、若干の見栄えや勝手の悪さは残りますけど…。

 

DIV タグだけで分割する

コンテンツ領域を DIV にしたのだし、メニュー領域こそ幅を指定してあるので DIV タグに差し替えても問題ないでしょう…、ということで、メニュー領域も DIV タグに変更してみました。スタイルシートはそのままです。

<!-- メニュー表示用の領域 -->

<div class="menu_style">

---- メニューデータをここへ記載します ----

</div>

 

<!-- コンテンツ表示用の領域 -->

<div class="contents_style">

---- コンテンツデータをここへ記載します ----

</div>

こうしてみても SPAN を混ぜていたときとまったく同じ感じでページを参照することが出来ました。どちらでも良いのかもしれませんけど、統一しておいた方が後々に見やすかったりするので、両方とも DIV タグで構成しておくのが良いかもしれないですね。

 

□ レイアウトの崩れを調整する

これまでの方法で問題なく表示されると思っていたのですけど、あるときこれまでの方法で作成していたページの表示が崩れてしまうとの知らせを受けました。

Windows XP Professional 上の Internet Explorer 6.0 にて調べてみると、たとえばコンテンツ領域内に横長の画像を配置したりした場合に上手く表示できなくなってしまうようでした。具体的にはメニュー領域を右に回りこませた後の空間にコンテンツ領域が入りきらなくなってしまって、結局はコンテンツ領域が次の行へ折り返されてしまうという感じでした。

これだと少し都合が悪いので、崩れずに済む方法がないか検討してみることにします。

 

余白を作って、そこへ回り込ませる

スタイルシートの float を使って回り込ませる場合、回り込ませたオブジェクトは余白の上に配置できるようです。今回の場合で言うと、メニュー領域を右に回りこませて、コンテンツ領域は右に余白を取っておくことでメニュー領域に干渉しないようにする感じです。

そうするために、スタイルシートを次のように変更してみます。

<!-- コンテンツ領域用のスタイル -->

.contents_style

{

width: 100%;

height: 100%;

overflow: auto;

 

margin-right: 200px;

}

 

<!-- メニュー領域用のスタイル -->

.menu_style

{

width: 200px;

height: 100%;

overflow: auto;

 

float: right;

}

コンテンツ領域に右余白 ( margin-right ) を設定し、メニュー領域をそこへ回りこませられるようにしておきます。 今度は余白として空間を設定しましたから、コンテンツ領域自体は画面いっぱいで大丈夫でしょうと思って "width: 100%" も追加してみました。

こうした上でメニュー領域を最初に、続いてコンテンツ領域を表示させます。

<!-- メニュー表示用の領域 -->

<div class="menu_style">

---- メニューデータをここへ記載します ----

</div>

 

<!-- コンテンツ表示用の領域 -->

<div class="contents_style">

---- コンテンツデータをここへ記載します ----

</div>

こうしてみると、コンテンツ領域に大きい画像を含ませても Windows XP Professional の Internet Explorer 6.0 で崩れずに表示できるようになりました。

ただ、Macintosh で確認してみると、Safari 2.0 なら期待通りの表示になってくれるのですけど、Internet Explorer 5.2 だとメニュー領域がコンテンツ領域の上にかぶさってしまう感じになってしまいました。コンテンツ領域の右側の一部がメニューの下に入ってしまってみることが出来ないですし、コンテンツ領域のスクロールバーさえも見えなくなってしまうのはけっこう困った感じでした。

 

余白を作って、そこに重ねる

右にメニューを置くときに、それを折り返し指定する方法だと、HTML にはメニューの情報が先に記述されることになります。

この場合、コンテンツ領域の表示が後回しになってしまうため、表示までに時間のかかるページだとメニューだけ表示されたまま少し待たされてしまう感じになることもあるそうです。それをコンテンツ領域から先に表示させるために、少し工夫をしてみることにしました。

方法としては、先にメニュー分の余白を空けたコンテンツ領域を表示させて、後からその余白部分にメニュー領域を移動させるという方法です。

 

コンテンツ領域を先に表示させる都合で、HTML は次のように領域を交換させます。

<!-- コンテンツ表示用の領域 -->

<div class="contents_style">

---- コンテンツデータをここへ記載します ----

</div>

 

<!-- メニュー表示用の領域 -->

<div class="menu_style">

---- メニューデータをここへ記載します ----

</div>

そして、スタイルシートを調整します。

<!-- コンテンツ領域用のスタイル -->

.contents_style

{

width: 100%;

height: 100%;

overflow: auto;

 

margin-right: 200px;

}

 

<!-- メニュー領域用のスタイル -->

.menu_style

{

width: 200px;

height: 100%;

overflow: auto;

 

 

position: absolute;

 

right: 0;

top: 0px;

}

変更点としては、メニュー領域の右寄せ指定 ( float: right ) を消して、メニューの位置を直接指定する "position: absolute" を指定します。そしてその指定位置として、ウィンドウの一番上 ( top: 0 ) の一番右端 ( right: 0 ) を指定します。

コンテンツ領域にはメニュー分の余白 ( margin-right: 200px ) が指定されていますので、その余白にメニューが配置されることになります。

 

こうしてみると、こちらの場合もコンテンツ領域に大きい画像を含ませても Windows XP Professional の Internet Explorer 6.0 で崩れずに表示できるようになりました。

ただ、Macintosh で確認してみると、今度は Safari 2.0 でもメニュー領域がコンテンツ領域の上にかぶさってしまう感じになってしまいました。スクロールバーも見えなくなってしまってます。そしてさらに Internet Explorer 5.2 だと、コンテンツ領域のみがいっぱいに表示されて、メニューバーはまったく表示されなくなってしまいました。

 

幅の指定を省略してみる

Macintosh で確認するとメニューが重なってしまうのは、もしかするとコンテンツ領域の幅の指定 ( width: 100% ) が影響していたりするのかなと思って、ちょっとそれを削除してみることにしました。

そうして Safari 2.0 にて確認してみたところ、先ほどまで重なってしまっていた 【余白を作って、そこに重ねる】 方は若干スクロールバーがメニューにかかってしまいましたけど、それでも問題ないといえるくらい、正常に表示されることが出来ました。ただし 【余白を作って、そこへ回り込ませる 】 方は Internet Explorer 5.2 だとメニューが表示された状態から、さらにメニューひとつ分の余白が空いてしまって、なんだか微妙な感じです。

Internet Explorer で確認してみると、これは Windows の 6.0 でも Macintosh の 5.2 でも、【余白を作って、そこに重ねる】 方も 【余白を作って、そこへ回り込ませる】 方も、どちらとも問題なく表示させることが出来ました。こちらも Macintosh ではスクロールバーが僅かにメニューに隠されてしまう感じではありますけど。

 

けれど、大事な問題点がひとつありました。

【余白を作って、そこへ回り込ませる】 方法で幅の指定を取り外してしまった場合、表示可能な幅を超える画像などがコンテンツ領域に含まれていたりしたときにコンテンツ領域が次の行へ送られてしまう現象が再び発生してしまったのでした。

【余白を作って、そこに重ねる】 方法で幅指定を取り外した場合だと、こちらは問題なく表示されてくれましたので、今のところこの方法が試してみたブラウザの中では一番、再現性が高いのではないかと思います。

 

□ 問題点

もっと慎重に吟味すれば何とか調整できるのかもしれないですけど、やっぱりフレームやテーブルを用いた方法よりは再現性は低くなってしまうような感じがします。

メニューが右側だったり、左側の領域幅が決まってないから難しいのかとも思ったのですけど、80% + 20% で分けてみても、Windows 版なら正常に見えるのですけど、Macintosh 版だと Safari 2.0 でも Internet Explorer 5.2 でも、どちらともコンテンツ領域が下へ折り返されてしまう感じになってしまいました。

Windows 版を想定しているだけなら簡単ですけど、Macintosh 版も考慮に入れると難しい、なんだかそんな感じです。

 

ちなみに両方をパーセンテージで指定する場合は、スタイルシートは次のような感じになります。

<!-- コンテンツ領域用のスタイル -->

.contents_style

{

width: 80%;

height: 100%;

overflow: auto;

 

float: left;

}

 

<!-- メニュー領域用のスタイル -->

.menu_style

{

width: 20%;

height: 100%;

overflow: auto;

 

float: right;

}

注意点としては、それぞれの領域に、右寄せ ( float: right ) と左寄せ ( float: left ) を指定する必要があるようでした。


 

カスタム検索

copyright © Tomohiro Kumagai @ EasyStyle G.K.
contact me: please from mail-form page.