*はじめに
最近のWebサイト業界において2カラムレイアウトは、見ない日がないほど普及している。にもかかわらず、いざこれを実現しようとすると、いまだに多くの面倒な問題にぶつかってしまう。例えば、containerの中にbodyとsidebarを配置するようなごく単純なdivレイアウトを考えよう。何も考えずに書くと、以下のようになるだろう。
**HTML
#geshi(html4strict){{
二段組みレイアウトのサンプルです。
メインテキスト
メインテキスト
メインテキスト
}}
**CSS
#geshi(css){{
#container {
width: 300px;
margin-left: auto;
margin-right: auto;
}
#body {
width: 200px;
float: left;
background-color: orange;
}
#sidebar {
width: 100px;
float: left;
background-color: skyblue;
}
}}
これをFirefox3.5で解釈すると次のようになる。

図1:下端が揃わない
図1より、背景色の下端が揃っていないことが分かる。これを解消するためには「子要素sidebarとbodyの下端を親要素containerの下端まで伸ばす」という指定を入れる必要があるが、実はこのような指定を簡単に書く方法がCSS3.0には用意されていない。このため、多くのトリッキーな方法が考案され、バッドノウハウとして広まっているのが現状である。
本記事の目的はこうした2カラムレイアウト関連のテクニックを整理することであり、このようなひどい状況を作ったCSSの仕様に苦言を呈すことであり、そしていつの日か、簡単に2カラムレイアウトが実現できるような仕組みが導入されることを、みなさんと一緒に祈ることでもある。
本記事では最終的に、
-背景の下端が揃った2カラムレイアウトである。
-幅も高さも固定せずに組める。
-それぞれのカラムに独立した透過pngが貼り付けられる。
-HTMLとCSSのファイルが1つずつあれば組める。
-javascriptを無効にしていても外観が変わらない。
-多くのブラウザで外観がほぼ一致する。
というレイアウトを目指す。
*結論
最初に結論を述べておく。現時点では、テーブルタグを用いたレイアウトが最もよい。それは、CSSによるレイアウトが決定的に能力不足だからである。
本エントリでは多くの環境で平等に閲覧できるようにするため、javascriptを不使用とした。したがって使用できるのはhtmlかCSSである。htmlの本分はマークアップなのだから、CSSでレイアウトを組むのが順当だという意見も確かにあるだろう。実際2カラム問題に関しては実にいろいろなCSSハックが提案されており、そのどれもが一見それなりに成立しそうなソリューションになっている。
しかし、私が確認できたすべての方法は、決して無視できない重大な欠陥を含んでいた。詳細はこれから説明するが、要約するとその内容は
-リキッドレイアウトにできない。
-アンカータグが動作不良をおこす。
-非透過の背景画像でしか使えない。
というものである。このどれもが用途によっては致命的である。
私が本記事でテーブルレイアウトを推すのは、CSSがいまだに2カラムレイアウトを正しく組める段階まで成長していないと考えているからである。今後状況が改善され、CSSで組みたいレイアウトが組めるようになり、大半のブラウザでそれが正しく解釈できるような時代が来れば、そのときには本記事のような次善の策は捨ててしまえばよい。残念ながら私たちは未来ではなく現在に生きているので、まずはともかく、既存のCSSレイアウトのどこがいけないのかを見ていこう。
*有名な3つの手法の紹介
**1.containerに背景画像を用いる
bodyとsidebarのwidthを固定しておき、これらの背景画像を連結した新たな画像を用意する。この画像をcontainerの背景画像として並べれば、bodyとsidebarに独立した画像を設定した場合と異なり、下端が一致したレイアウトとなる(図2)。

図2:containerに背景画像を用いる
#geshi(css){{
#container {
width: 300px;
margin-left: auto;
margin-right: auto;
background: transparent url(background.png) repeat scroll 0 0;
}
#body {
width: 200px;
float: left;
}
#sidebar {
width: 100px;
float: left;
}
}}
この手法の問題はリキッドレイアウトにできない点だ。つまり、どのようなディスプレイから見ても同じ横幅となるよう、widthを固定しておく必要がある。このことは閲覧者側にも管理者側にもデメリットとなる。
閲覧者側のデメリットは、狭いディスプレイで読みにくくなるという点である。高解像度の液晶ディスプレイはずいぶん普及したが、ネットブックやスマートフォンなどの登場によりいまだに低解像度のディスプレイは広く使われている。iPhoneのようにダブルタップで読みたいブロックを簡単に拡大できるならよいが、そうでない端末を使っている場合、PC用に最適化された幅のコンテンツを読むのは面倒だろう。
管理者側にもデメリットがある。レイアウトを容易に変更できないという点だ。メインカラムやサイドバーの横幅を少し調整するたびに新しい背景画像を用意するのは時間の無駄である。
**2.縦方向のネガティブマージンを用いる
これは大きなpadding-bottomを与えることで背景画像をはるか下方まで伸ばし、同じ絶対値を持つ負のmargin-bottomで下方向の隙間をキャンセルする方法である。containerを越えて伸びた背景画像は、overflow:hiddenを指定して隠す(図3)。

図3:ネガティブマージンを用いる
具体的には次のようにする。まず絶対値の等しい正負の二整数N,-Nを用意する。このときの整数は例えばN=2^15=32768がよく用いられる。bodyとsidebarに-Nのmargin-bottomとNのpadding-bottomを設定し、containerにoevrflow:hiddenを指定する。
#geshi(css){{
#container {
width: 300px;
margin-left: auto;
margin-right: auto;
overflow: hidden;
}
#body {
width: 200px;
float: left;
background-color: orange;
padding-bottom: 32768px;
margin-bottom: -32768px;
}
#sidebar {
width: 100px;
float: left;
background-color: skyblue;
padding-bottom: 32768px;
margin-bottom: -32768px;
}
}}
この方法の問題点はアンカータグが正常に動作しないことである。アンカータグとは、ページ内リンクを貼るためのタグである。このタグは長めの文章に目次をつけるときや、ブログのコメント部、トラックバック部に直接リンクを張りたい場合などに便利だが、ネガティブマージンを使う場合は別の方法を考えなければならない。この意味で、縦方向のネガティブマージンはサイト構成の選択肢を著しく狭めていると言えるだろう。
なお、次のURLに動作不良のサンプルがある。
-ネガティブマージン+overflow:hiddenにアンカーを組み合わせると絶望的な件に関して – やさしいデスマーチ
–再現ページ
**3.前景と背景に異なるdivブロックを用いる
これは、body,sidebarそれぞれの前景と背景を分離して扱う方法である。背景のdivブロックを重ねて配置し、rightを用いてbodyに対応する背景を左方向に移動する。overflow:hiddenで左にはみ出した分を隠せば2カラムレイアウトの背景のように見せかけることができるので、leftを用いて適切な位置に前景であるbodyとsidebarのテキストを配置してやればよい(図4)。

図4:前景と背景に異なるdivブロックを用いる
CSSは次のようになるだろう。
#geshi(css){{
#containerbody {
width: 300px;
float: left;
position: relative;
right: 100px;
background-color: orange;
}
#containersidebar {
width: 300px;
margin-left: auto;
margin-right: auto;
overflow: hidden;
background-color: skyblue;
}
#body {
float: left;
position: relative;
width: 200px;
left: 100px;
}
#sidebar {
float: left;
position: relative;
width: 100px;
left: 100px;
}
}}
この方法の問題点は背景に透過pngを用いることができない点である。bodyの背景とsidebarの背景が重なっており、bodyに透過pngを用いるとsidebarの背景と混ざってしまうからだ。デザイン上透過pngを使わないのであればこの方法を用いればよいが、そうでない場合は別の方法を模索する必要がある。
*その他の手法
以上よくある3つの手法を見た。ここではその他の手法と問題点を簡単に列挙しておく。
**4.絶対配置を用いる
-2と同様リキッドレイアウトにできない。
-計算が面倒。
-ブラウザによって解釈が異なることがあり、1dot単位での厳密な配置を行うと特定のブラウザでレイアウトが崩れる可能性がある。
**5.height: 100%を用いる
-カラムの高さを固定するか、ブラウザの高さに対する相対値にする必要がある。
**6.Display: tableを用いる
-Internet Explorer7以下では動作しない。
*テーブルレイアウト
以上見てきたように、CSSの2カラムレイアウトには、重要なブラウザで動作しなかったり、ユーザビリティを制限してしまったりといった不具合がどうしてもつきまとう。この状況は当分解決されそうにないので、別の方法を考えるべきだ。ではどんな方法がよいだろうか。私が考える現時点での最適解は、太古のWebから存在する手法、いにしえのソリューションであるところのtableタグを用いる方法である。HTMLとCSSは例えば次のようになる。ネガティブマージンもposition:relativeも出てこない、非常に単純明快なコードになっている。
**HTML
#geshi(html4strict){{
}}
**CSS
#geshi(css){{
#container {
width: 300px;
margin-left: auto;
margin-right: auto;
}
table{
border-collapse: collapse;
}
td.body {
background-color: orange;
vertical-align: top;
width: 200px;
}
td.sidebar {
background-color: skyblue;
vertical-align: top;
width: 100px;
}
}}
*議論
ちょっとまった、という声が聞こえてくるかもしれない。htmlはマークアップのための言語だ。デザインとは切り離すべきである、と。tableタグはそこに表組みがあるということだけを意味しており、レイアウトという文脈は込められていない。Webサイトのメインコンテンツとサイドバーがまるまるtableの中に入っているのは不自然だ、と。
しかし、このご時世、tableレイアウトを解釈できないブラウザがいったいどれだけあるというのだろうか。少なくともレンダラ部を備えたブラウザでは皆無に近いはずだ。私が試した限りにおいては、このテーブルレイアウトは
-Internet Explorer 6,7,8
-Mozilla Firefox 3.0, 3.5
-Google Chrome 1.0
-Safari 4.0
-Netscape 7.1
の全てで正しく表示されている。これらは2009年現在のブラウザシェアの9割を越えている。
テキストブラウザでは読めないかもしれないという意見があるかもしれないので、これに関しても調べてみたが、W3Mはテーブルを正しく2段で表示したし、Lynxも1段ずつ左から順にテーブルの中身を表示した。これはコンテンツ左、サイドバー右という形式のレイアウトなら本文が先に来るのでほとんど問題ないし、あまり見かけないがその逆のレイアウトであっても、サイドバーに[PageDown]で追いつかないほど大量の情報は入らないだろうから、そこまで大きな問題にはならないと考えられる。そもそも、テーブルレイアウトはかなりありふれた構成だから、テキストブラウザなどというマイナーブラウザを使うマニアックな人にとっては扱いやすいもののはずだ。自力でどうとでもするだろう。
唯一問題になると考えられるのはスクリーンリーダを使っている視覚障害者の方へのサポートであり、これはCSS、テーブルのいずれを使っても難しく、完全を目指すなら専用ページを用意するという形になるだろう。だが、それなりの対応でよいならば、これに関しても現状ではテーブルタグの方が有利である可能性が高い。というのも、例えばNVDA日本語を用いる場合、Ctrl+Alt+矢印キーでテーブル内の移動ができるので、どういう順番で並んでいるのか分かりづらい上に濫用されがちなdivタグをさまよい歩くよりは、行と列がはっきりしているtableタグのメインカラムとサイドバーを行き来する方が楽だからである。
ここまで説明してもまだ「モダンなサイトはCSSレイアウトで組んであるに違いない」とかたくなに信じている方のために、最後にテーブルレイアウトを用いている有名なサイトを紹介しておこう。Twitterだ(2009年12月現在)。嘘だと思うなら、Twitterを開いてソースを確認してみるとよい。タイムラインとサイドバーがテーブルで分けられていることが確認できるはずだ。あなたは、Twitterを読んでいてレイアウトの問題で何か不自由したことがあるだろうか?

図5:Twitterはテーブルレイアウトを利用している
*まとめ
そういうわけで、2カラムレイアウトはtableを使うのがよいというのが私の結論である。そういうわけで、このサイトはWordPressという最先端のブログツールを駆使していながら、テーブルレイアウトのような古錆びたテクニックを背負っている。レトロなフューチャーとモダンなノスタルジーの境目も曖昧になってきたゼロ年代の終わりだからこそ、こういうサイトが始まってもいいよね。そういうわけで、テルパラはこんな解説記事からスタートしました。
来年もどうぞ、よろしくお願いします。