「擬似フレーム(疑似フレーム)」の作り方(IE6 にも対応、スタイルシート(CSS)、JavaScript使用)
このページでは、フレームを使わずに、 フレームを使ったサイトと同じ見た目と動作を実現する方法を解説します。 一般に、 「擬似フレーム」とか 「疑似フレーム」とか 「CSSフレーム」とか 「overflowフレーム」と呼ばれているもののことです。 ここで解説している方法の特徴は、以下の通りです。
- { position: fixed } 未対応の
IE6 (IE: Internet Explorer) でも動作します。
IE7, NN6 以上 (NN: Netscape Navigator), Mozilla, FireFox, Opera, Sleipnir にも対応しています。 - このサイトのような複雑なフレーム分割にも対応できます。
そのために JavaScript を使用しています。
(JavaScript が使えない環境で閲覧した場合、フレーム風には表示されませんが、 特に書式が指定されずに無理のないスタイルで表示されます。 lynx 等での動作も 確認済みです。)
なお、縦のみ及び横のみのフレーム分割の場合、 JavaScript を使用しなくても作成できます。 以下のサイトにそれらの解説や例があります。
スタイルシートで疑似フレーム(解説+サンプル)
横分割サンプル(フランス語)
縦分割サンプル(フランス語)
フレームを使ったサイトは、メニュー部分がスクロールしないので利用者にとって使い易く、 メニューのデータが多数の HTML ファイルに分散せずに1つのファイルにあるので、 サイト構成を変更したときもメンテナンスが楽という利点がありますが、
- 個々のページを URL で紹介できない
- フレーム内の個々の HTML にリンクを貼られると、それをたどってきた利用者が混乱しやすい。
- SEO 対策上も不利。
という欠点があります。そこで、フレームを使わずに、フレームを使ったサイトの良さを、 スタイルシートと JavaScript を駆使して実現する方法をご紹介します。 縦横のフレーム分割が多数あるような構成のサイトも置き換え可能です。
それでは、「擬似フレーム(疑似フレーム)」や「フレーム風サイト」とでも呼ぶべきサイトを 実現している方法をこれから書いていきます。
なお、メニューなどの共通部分を一つのファイルのみで管理する方法については、
自動生成メニューの作り方の方をご覧下さい。
概要
「擬似フレーム(疑似フレーム)」/「フレーム風サイト」を実現するために使っている技術の解説は、
要約すると以下の 1. 〜 3. の通りです。
1. 個々のページの HTML ファイルでは、 <body>〜</body> で囲まれた部分に、
- <div id="header">〜</div>
- <div id="lt">〜</div>
- <div id="headmenu">〜</div>
(上メニューがあるページのみ) - <div id="main">〜</div>
という要素のみを書きます。それぞれ、
ヘッダバナー、左メニュー、上メニュー、本文部分に相当し、
フレームのように動作します。
2. スタイルシートを用いて以下のことを指定します。
- ブラウザのスクロールバーを消す。
html{ overflow: hidden; } - body 領域の内寸をブラウザの内寸に一致させる。
html{ height:100%; } body{ height:100%; width: 100%; } - #lt, #main に、
内容が領域内に表示しきれなくなったらスクロールバーを表示するように指定する。
{ overflow: auto; } - #header, #lt, #headmenu, #main に、
{ position: absolute; } を指定する。
(これにより、位置がページ上での絶対座標で指定できるようになる。 IE6 も対応可。)
3. ページロード時 (onload) 及びページサイズ変更時 (onresize) に、 JavaScript を用いて、ブラウザの表示領域の内寸を取得し、それを元に
- <div id="header">〜</div>
- <div id="lt">〜</div>
- <div id="headmenu">〜</div>
(上メニューがあるページのみ) - <div id="main">〜</div>
という領域の適切な大きさと位置を計算し、それぞれに指定しています。
個々の部分の詳しい解説を以下に記載します。
HTML
ページの作りは、以下に示します。(抜粋)
まず、 HTML ファイルのはじめの部分です。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja"><head>
HTML の開始部分です。特に他のページと違うところはありません。
このサイトでは、ページを読み込む時点でページの各部分の表示位置が必ずしも正確ではなくても、
後から JavaScript で正しい位置に動かします。
ですから、 loose.dtd を指定しても、特に問題はありません。
(strict の方を指定してもでも全く問題はありません。)
次は、ヘッダ(<head> 〜 </head>)のはじめの部分です。
<script type="text/javascript" src="shared.js"></script> <script type="text/javascript" src="head.js"></script> <script type="text/javascript" src="site.js"></script>
この部分は、全ページ共通の各種外部スクリプトファイルの読み込みと、
ページ個別のコードです。
次は、ヘッダ(<head> 〜 </head>)の続きと、
全ページ共通のヘッダのバナーとメニューの部分です。
<title>編集後記</title> </head><body> <div id="header"><!-- ここはヘッダです --> <script type="text/javascript" src="header.js"></script> </div><!-- id="header" ここまでヘッダです --> <div id="lt"><!-- ここは左メニューです --> <script type="text/javascript" src="lt.js"></script> <a href="sitemap.html" class="sitemap">サイトマップ</a> </div> <!-- id="lt" ここまで左メニューです --> <div id="main"><!-- ########## ここから本文です ########## -->
この部分では、ヘッダのバナーと左メニューを出力するスクリプト
("header.js", "lt.js")を読み込んでいます。
<div id="header"> と </div> 、
<div id="lt"> と </div> 、
<div id="headmenu"> と </div> 、
<div id="main"> と </div> で囲まれた部分は、
それぞれ一つのフレームの様に動作します。これらも全ページ共通です。
それぞれの部分で読み込んでいる "header.js" と "lt.js" は、
外部 JavaScript ファイルなので、全てのページから同じものを読み込んで使用することが出来ます。
左メニューの中には、マウスカーソルを持ってくると背景が変わるなど、
JavaScript で動作する部分もありますが、これも JavaScript で出力しています。
つまり、 "lt.js" には、 JavaScript を書き出す( = document.write() )
JavaScript が書いてあります。こちらについての解説は、
自動生成メニューの作り方の方に書きました。
次は、ページの最後の部分です。
<a href="sitemap.html" class="sitemap_white">サイトマップ</a> <div class="footer"> <script type="text/javascript" src="footer.js"></script> </div> <!-- class="footer" --> </div> <!-- id="main" --> <!-- ########## ここまで本文です ########## --> </body> </html>
"footer.js" は、フッタを出力するスクリプトです。これも全ページ共通です。
CSS
次に、スタイルシートの方を見ていきます。 JavaScript がブラウザを判定し、
IE6以降、NN6以降、FireFox など、十分な機能をもつブラウザであると判定した場合、
style.css というスタイルシートを読み込みます。
まずは、html と body の部分です。
html{
height:100%;
overflow:hidden;
}
body{
height:100%;
width:100%;
margin:0px auto;
}
まず、 html と body の領域を、ブラウザの内寸に一致させるとともに、
スクロールバーを消しています。
次は、フレームのように動作する、ページの大きな構成要素(header, lt, headmenu, main)です。
#header{
position: absolute;
width: 100%;
height: 70px;
margin: 0px;
border: 0px;
padding: 0px;
background-color: #003366;
}
#lt{
position: absolute;
left: 0px;
top: 70px;
bottom: 0px;
width: 156px;
overflow: auto;
background-color: #003366;
color: #ffffff;
}
#headmenu {
position: absolute;
left: 156px;
top: 70px;
right: 0px;
height: 45px;
margin: 0px;
background-color: #ffffff;
}
#main{
position: absolute;
left: 156px;
top: 115px;
right: 0px;
bottom: 0px;
overflow: auto;
background-color: #ffffff;
color: #000000;
}
ヘッダのバナー、左メニュー、メインを順次配置しています。
それらの位置を JavaScript でページ内での絶対座標を用いて指定できるようにするために、
{ position: absolute; }
を必ず指定しておきます。
なお、それぞれの表示位置は、スタイルシートである程度指定するのみならず、
JavaScript を onload と onresize のイベントで呼び出して、
ブラウザの Window のサイズに合わせて適切な位置を計算し直して指定します。
また、左メニューの表示領域(lt)とメインの表示領域(main)には、
{ overflow: auto; }
を指定し、内容が表示領域内に収まらなくなったらスクロールバーを表示するように指定しています。
JavaScript
CSS の指定だけでは、残念ながら上記の各主要構成要素(header, lt, headmenu, main)を
正しい位置に配置することが出来ないので、
onload と onresize のイベントが発生する度に、
下記の arrange() を呼び出しています。
function arrange() {
if( 0 == g_browser_ok ) {
return;
}
var obj = window;
if( window.opera ) {
var w = obj.innerWidth;
var h = obj.innerHeight;
} else if( document.all ){ //ie4-
var w = obj.document.body.clientWidth;
var h = obj.document.body.clientHeight;
} else if( document.getElementById ){ //n6-7, m1, s1
var w = obj.innerWidth;
var h = obj.innerHeight;
}
まず、ブラウザの機能が十分であることを確認してから、
ブラウザに応じた方法で、ブラウザの内寸を取得します。
var header_style = document.getElementById("header").style;
header_style.left = 0 + "px";
header_style.top = 0 + "px";
header_style.width = w + "px";
header_style.height = 70 + "px";
var lt_style = document.getElementById("lt").style;
lt_style.left = 0 + "px";
lt_style.top = 70 + "px";
lt_style.width = 156 + "px";
lt_style.height = ( h - 70 ) + "px";
var headmenu_style = document.getElementById("headmenu").style;
headmenu_style.left = 156 + "px";
headmenu_style.top = 70 + "px";
headmenu_style.width = ( w - 156 ) + "px";
headmenu_style.height = 45 + "px";
var main_style = document.getElementById("main").style;
main_style.left = 156 + "px";
main_style.top = 70 + 45 + "px";
main_style.width = ( w - 156 ) + "px";
main_style.height = ( h - 45 - 70 ) + "px";
}
取得したブラウザの内寸に応じて、各部分(header, lt, headmenu, main)の大きさを計算し、
それぞれのスタイルとして設定します。
この部分のコードを変更すれば、自由なレイアウト構成が可能です。
欠点とその解消
「擬似フレーム(疑似フレーム)」は、メニューが動かないので、 メニューを段組で構成しているサイトと比べて閲覧に便利であり、 フレームを使ったサイトと違ってフレーム内リンクの問題が生じないなど利便性が高く、 当サイトでも採用しているのですが、 一般には、以下のような欠点・問題点があるとされています。
- 印刷がうまくできない。
- 本文をスクロールして表示する領域が狭い。
- 新たなページを開く度に、メニューのような共通部分も毎回ダウンロードしないといけない。
当サイトでは、これらの問題点を全て解決しています。 その方法をこれからに紹介していきます。
印刷
擬似フレームを利用し、印刷に特に配慮しない場合、 おおよそ画面通りのイメージで、スクロールバーまで含めて印刷されます。 そして、表示範囲に収まっていない部分は印刷されません。 対策は割に簡単で、印刷用のスタイルシートを作成することで出来ます。
まず、印刷用のスタイルシートを作ります。 一つのスタイルシートで画面用と印刷用の両方の記述を行うことも出来るのですが、 今回は2つに分けました。 まず、両方のスタイルシートを読み込むためのタグを <head>〜</head> に記述します。
<link href="style.css" rel="stylesheet" type="text/css" media="all"> <link href="print.css" rel="stylesheet" type="text/css" media="print">
次に、メニュー部分を印刷から消します。
メニューは、画面上でサイト内をアクセスするときには便利ですが、
印刷してしまったら利用価値はなく、紙が無駄になってしまいますし、
デザイン上もページ本文とは異質のものですので、すっきりさせるために削除することにしました。
#header,#lt{
display: none;
}
.sitemap {
display: none;
}
そして、一番大切なのが、本文部分の設定です。
本文は、 JavaScript による位置の指定に影響されてしまわないようにする必要があります。
また、画面では枠内に入らずスクロールする部分も、全て印刷されなくてはいけません。
前者は、 position: static; で、
後者は、 overflow: visible; で対処できます。
このサイトでは、ページ内リンクは、印刷しても目次として役立つと考えたので、
"headmenu" の部分も印刷することにしました。
#headmenu, #main{
position: static;
width: auto;
height: auto;
overflow: visible;
}
これだけで、印刷してもきちんと読めるようになります。 なお、他のいくつかのタグについても、色などを適宜設定しても良いと思います。
本文表示領域
スクロール可能な領域は、メニューの分だけ狭くなってしまいます。 これに対処するため、メニューやバナーに伸縮機能をつけました。 対処方法は、上記の arrange() 関数を少々加工し、 伸縮ボタンをクリックしたときにそれを呼び出し、 <head>〜</head>, <lt>〜</lt>, <headmenu>〜</headmenu>, <main>〜</main> の各部分の位置と幅を変えて配置し直すというものです。 このページにも付いていますので、利用可能な環境にある方は是非とも試してみてください。
共通部分
このサイトでは、メニューなどの共通部分は、各々の HTML ファイルに記載してあるのではなく、 ヘッダバナーは "header.js" が、メニューは "lt.js" という JavaScript が それぞれ生成し、各々の HTML ファイルではそれを呼び出しているだけです。 ですから、新しいページを開く度に共通部分をダウンロードするということはありません。
動作確認ブラウザ
| ブラウザ名 | 動作 |
| Internet Explorer 6 | ◎ |
| Internet Explorer 7 | ◎ |
| FireFox 1.5 - 2.0 | ◎ |
| Netscape 7.2 | ◎ |
| Mozilla 1.6 | ◎ |
| Safari 2.0.4 | ◎ |
| Opera 9.02 | ◎ |
| Sleipnir 2.64-2.66 | ◎ |
| lynx | △ |
| IE 5.0-5.5 | △ |
| Mac IE 5 | △ |
| Netscape 4.x | △ |
| 対応状況が △ のものは、スタイルシートを読み込みません。 このサイトは、サイトマップを用意して全ページの上下にそこへのリンクを表示するなどし、 スタイルシートや JavaScript を読み込まなくても支障なく閲覧できるように作ってあります。 | |
名称について
このページでは、このページのようなページの作り方を
「擬似フレーム(疑似フレーム)」と呼んでいます。
この名称が最も普及しているので採用しました。
ただ、「擬似フレーム(疑似フレーム)」とは何か?ということを考えてみると、
この名称が相応しいかには、若干の疑問が残ります。
確かに、このページの見た目や動作は、フレームを使用していないにもかかわらず、
フレームを使ったサイトに似ています。
また、「フレーム」という概念の認知度や理解度は一般に高いので、
「擬似フレーム(疑似フレーム)」という名称を初めて見た時に
その名称が意味する内容を正しく推測できる可能性は高いと思います。
ですから、「擬似フレーム(疑似フレーム)」という名称には、
一定の合理性や有用性があると思います。
しかし、あるブロック要素の中に
{ overflow: scroll }
を指定出来るということは、
もともとスタイルシート (CSS) の機能の一部として存在しているわけですから、
それを使った結果、たまたまフレームに似たからといって、
それを使うことを「擬似フレーム(疑似フレーム)」と呼ぶことは、
その本質を表した表現ではないようにも思います。
その本質を直接表現するのであれば、例えば、
「ページ部分スクロール」等と呼ぶのが相応しいかもしれませんし、
IFRAME 風ではなくて、
ブラウザのページ表示部分をフレームで分割するサイトの様であるということを強調するならば、
「ブラウザ分割スクロール」などと呼ぶのが相応しいかもしれません。
ただ、これらの名称は、抽象度が高いので、イメージが沸きにくく、
初めて見たときにこれらが意味する内容を正しく推測できる可能性が高くないという
欠点があると思います。
このサイトでは、「擬似フレーム(疑似フレーム)」という名称を使うときは、
それが必ずしも適切な名前ではないかもしれないという問題意識を持っているということを表すために、
かならず「」で囲って使用しています。
「擬似フレーム(疑似フレーム)」という名称に疑問を感じる人は、
どうやら私だけではないようですので、疑問を感じる理由を分析して記述してみました。
擬似フレームの問題点:
http://ima.pandach.com/ch/Flame_03.php
また、「擬似」と「疑似」のいずれがより相応しいかについて考えてみると、
個々の漢字の意味に注目して考えた場合は、
「なずらえ」、「まがい」、「もどき」といった訓を持つ「擬」の方が、
「うたがい」といった訓を持つ「疑」よりも相応しいと思うのですが、
どちらが世間一般で多く用いられているかに注目して考えた場合、
「擬似」と
「疑似」をそれぞれGoogleで検索すると
「疑似」の方が多く見つかりますし、
「擬似フレーム」と
「疑似フレーム」では、
さらに大きな差で
「疑似フレーム」
の方が多く見つかりますので、
「疑似フレーム」という表現を外すわけにはいかないと考え、
「擬似フレーム(疑似フレーム)」と表記することにしました。
追記:(2006/12/11)
最近、「CSSフレーム」とか
「overflowフレーム」といった表現も目にしたことがあります。
これらの表現は、「フレーム」に修飾語が付いていることにより
「擬似」であることを表現していますし、
「CSS」とか「overflow」といった言葉で「擬似フレーム」を実現するための手段を表していますので、
これらの表現の方が「擬似フレーム」よりも本質を表しているように思いますが、
残念ながらそれほど広く使われていないようです。
参考資料
IE6でもスクロールしても動かないボックス:
http://www.stylish-style.com/csstec/ultimate/fixbox-ie6.html
スタイルシートで疑似フレーム(解説+サンプル):
http://desperadoes.biz/style/p_frame.php
横分割サンプル:
http://css.alsacreations.com/modeles/modele13.htm
縦分割サンプル:
http://css.alsacreations.com/modeles/modele14.htm
高密度商業地域 - 擬似フレーム:
http://komitsudo.blog70.fc2.com/blog-entry-32.html
擬似フレームの問題点:
http://ima.pandach.com/ch/Flame_03.php
八上全弘
更新履歴:
2006年10月15日 初回作成(appendix.html)
2006年11月07日 「疑似フレーム」の作り方をこのページに移動。
2006年11月24日 ページの title を、
「IE6対応「疑似フレーム」の作り方(スタイルシート(CSS)、JavaScript使用)」から
「「擬似フレーム(疑似フレーム)」の作り方(IE6 にも対応、スタイルシート(CSS)、JavaScript使用)」に変更。
2006年11月25日 「名称」という項目を追加。
2006年12月01日 「欠点とその解消」という項目を追加。