この日記のcssを書いた時に感じたことのまとめ。
前に書いたの。
これらを元に一旦まとめておきます。わりと初心者向けっぽく書いたつもり。でも自分で読んでみて意味が分かりません。
なお、この文におけるIE(InternetExplorer)は互換モード前提。そもそもxml宣言があるxhtmlを標準モードで解釈しないIEが悪いのですけど。
マークアップ
blogはほとんどの場合、記事単位で読まれることが多いと思うので閲覧者にとっては不要かもしれませんが、どんなblogでもまるで型にはめたようにsidebarというものが存在します。場合によっては左右にsidebarがあり、真ん中にコンテンツがある、いわゆる3カラムレイアウトというものもありますが、メインコンテンツの表示領域が狭くなることと、sidebarがそんなにあってもそこに入れるものが無いので、ここでは扱わないものとします。
さて。左右のどちらかにsidebarがあり、その隣にコンテンツを表示する、2カラムレイアウトですが、単純に書くと以下のようになっていると思われます。
<body>
<div id="header">ヘッダ</div>
<div id="container">
<div id="sidebar">サイドバー</div>
<div id="content">コンテンツ</div>
</div>
<div id="footer">フッタ</div>
</body>
- タイトルなどを記述するヘッダ。header
- ナビゲーション用のサイドバー。sidebar
- 本文を表示する部分。content
- 著作表示等のフッタ。footer
上記ソースではsidebarとcontentをcontainerで括ってありますが、無くても問題ないですね。
で、このソースを元にcssで2カラムにします。
floatによる右メニュー2カラム
div#header {width : 100%;}
div#container {width : 100%;}
div#sidebar {
float : right;
width : 20%;
}
div#content {
width : 100%;
margin-right : 20%;
}
div#sidebar + div#content {
width : 80%;
}
div#footer {
width : 100%;
clear : both;
}
100%の表示領域内で横幅20%のsidebarをfloatを右に配置した場合、それに続くcontentの横幅は80%と指定するべきなのですが、InternetExplorerにおいてはwidthプロパティの解釈が怪しく、表示可能な領域内に対する割合を指定しなければならないようです。なので、contentの横幅を100%とし、IEが解釈しない隣接セレクタを用いてCSSハック(のようなもの)します。
IEではdiv#contentへ指定したwidth:100%;のみを解釈し、それ以外のKHTMLやOpera,Geckoなどでは隣接セレクタdiv#sidebar + div#content(sidebarの直後にcontentが存在する場合に適用。)で指定したwidth:80%;が適用されるはずです。
floatによる左メニュー2カラム
(x)htmlソースを修正する必要はありません。sidebarを左にfloatさせ、contentのマージンも左側に20%とるようにします。
div#header {width : 100%;}
div#container {width : 100%;}
div#sidebar {
float : left;
width : 20%;
}
div#content {
width : 100%;
margin-left : 20%;
}
div#sidebar + div#content {
width : 80%;
}
div#footer {
width : 100%;
clear : both;
}
双方共に言えることですが、floatプロパティで配置する要素はwidthプロパティで幅を指定する必要があります。これに関して確かなことはわからないのですが、実害があることと言えば…IEにおいてwidthプロパティを指定していないブロック要素内でfloatを用いると文字欠けや画像が表示されない等の不都合が生じることがあります。
ボーダーが付くのはブロック要素の内か外か
内か外か、というのは確実な表現ではないかもしれません。
上記のソースで、各部にborderを追加した際の挙動がレンダラによって異なるのが気になったので試してみました。
まずはIE
ヘッダ、コンテンツ、サイドバーの隣接部のスクリーンショットです。赤がヘッダ、緑がコンテンツ、青がサイドバー。なお、ボーダーの幅は3pxです。
横幅100%のcontainer内に80%のコンテンツ、20%のサイドバーを並べて表示しています。ここでおかしいのは、何故か微妙にマージンがある、という事ですが、これはボーダーを付けなくてもマージンが設定されてしまうようなので無視するとして。
IEではブロック要素の内側にボーダーが付くのではないかと。
そしてKHTML
ご覧のように重なってます。また幅100%と指定したブロック要素がウインドウ外へはみ出てしまい横スクロールバーが表示されてしまいます。
正確に計算したわけではないので不確定ですが、恐らくこれはボックス要素の外側にボーダーが付くからではないかと。
なお、OperaやGeckoでもこれと同様に解釈します。
ボーダーが重ならないように配置するには、widthプロパティで指定する値に余裕を持たせる必要があるかもしれません。
余談ですが、両ブロック要素へpaddingを設定すると重なる幅が大きくなります。
----
この件について少々気になったのでwidth:100%;と指定している部分(header,container,footer)を100pxと指定して試してみました。
当然ですがこれだけ幅を狭めると表示は崩れます。
全体の幅が100pxで、contentは80%、sidebarが20%なので、各々80px,20pxとなっているはずです。
計ってみると、緑枠で囲っているcontentのボーダー内側、白い部分の横幅は確かに80pxです。同様に青いsidebarも内寸で20pxとなっています。そして緑のボーダーの外側から青のボーダーの外側までが100px。これはcontentとsidebarの親要素であるcontanerのwidthを100pxに指定しているからです。width:100px;のheaderは内寸で100px,外寸は106pxとなっています。つまり、ボーダーはブロック要素の外側に付く。なのでボーダー4本分(この例では12px)の幅が重なって表示されるのは当たり前、という事になりますね。
floatで配置したブロック要素が落ちる
まず、floatで右に寄せたsidebar、そして次にfloatをclearしないで表示させたcontent。こういったスタイルでは、ウインドウ幅を狭めていくと後から表示したブロック要素が下に落ちる事があります。Opera,Gecko,KHTMLなどといった先進的なブラウザではあまりこういった事は起こらないのですが、InternetExplorerにおいては特に起こりやすいです。
ブロック要素が下に落ちるのは、floatされたブロック要素に内在する要素の幅が親要素の横幅を越えた時。
自分で書いていながらなんて分かり難いんだろうと思うので簡単な例を挙げると……content内に横幅が640pxの画像を貼ったとします。そしてウインドウサイズを狭めていって、contentの横幅が640pxより小さくなった時。
同様に、横幅一杯になっても自動で改行されないもの。例えば、スペースの含まれていないアルファベットの羅列、などもこれに当たります。
こういったものは先進的なブラウザでは起こりにくいですし、bodyへmin-widthプロパティで最小幅を指定してやることで抑えることが出来るのですが、IEは残念ながらmin-widthに対応していません。諦めましょう。
またpositionプロパティでブロック要素を固定した場合はこの現象が起きないのですが、それ以外に問題があるので今回は扱わないこととします。
横幅を固定した2カラムレイアウト
ウインドウサイズによらず横幅が固定されたウェブページは、高解像度環境において少ししか表示されず見難い、また低解像度環境下においては横スクロールバーが表示されてしまいとても見られたもんじゃない。なのであまりオススメ出来ません。
…と、以前はよく言われていたものですが、最近の各種blogホスティングサービスのテンプレートは、どうもこの横幅固定レイアウトが多いようで。何故か分からないけどそれなりに需要があるという事でしょうか。止めて欲しいんですが。
UXGAのディスプレイ解像度でブラウザを最大化して横幅700px固定のページを読み込んだ例。ちょっとしか表示されずちんまりしょんぼり。
どうしても固定したい場合はcssをこんなふうに
div#header {
width:700px;
margin-left : auto;
margin-right : auto;
}
div#container {
width : 700px;
margin-left : auto;
margin-right : auto;
}
div#sidebar {
float : right;
width : 20%;
}
div#content {
width : 100%;
margin-right : 20%;
}
div#sidebar + div#content {
width : 80%;
margin-right : 20%;
}
div#footer {
width : 700px;
clear : both;
margin-left : auto;
margin-right : auto;
}
先ほどの、横幅を100pxに固定した場合の例と同じようにheader,container,footerのwidthを700pxに。またセンタリンさせる為にそれぞれにmargin-leftとmargin-rightでauto値を指定。ただしIEはmarginプロパティのauto値を解釈しない。
終わり
CSSを書く時は、ある程度まともに解釈してくれるKHTML,Opera,Gecko等を用いて確認し、最終的にIEに合わせる努力をしたほうが無難です。
IEを基準に書いた場合はそれ以外の先進的なブラウザへ合わせるのが結構大変だったりしますので。
あと最低限Validatorくらいは通すように。これでエラーが出るようなCSSを書いておきながらOperaで表示がおかしいとか言うなよソコの人。