さて、ここでは tableを使ったレイアウトのページをCSSを使ったレイアウトのページに書き改めてみましょう。
もとのテーブルレイアウトのページですが、中身の分量が少ないこともあって割合シンプルなページですね。段組こそありませんが、テーブルの入れ子や透明画像で隙間を空けるなどのよく使われる技法が入ってます。
ページの構造をみる
このページの中身を大まかに分けるとこんな感じです。ここではテーブルの罫線を赤で表示させました。本文とフッタを区切る水平罫線(hr要素)以外はすべてテーブルの中に入っていることがわかります。典型的なテーブルレイアウトですね。
「ヘッダ」はこの場合「見出し」としたほうがいいかもしれません。また「次へ」「戻る」などのナビゲーションはこのページではフッタにしかありません。
では順に見ていきましょう。まず HTML を書き直してあとで CSS で表示を整えます。
HTMLの書き直し
ここではテーブルレイアウトからCSSレイアウトに書き改めるのと同時に HTML4.01 Transitional から XHTML1.1 に変えることにします。
見出し
- 01: <table width="100%" border="0" cellpadding="0" cellspacing="0" summary="ヘッダ">
- 02: <tbody>
- 03: <tr>
- 04: <td valign="bottom">
- 05: <img src="img/t2.png" alt="Original" width="251" height="39">
- 06: <img src="img/blank.png" alt="" width="1" height="70">
- 07: </td>
- 08: <td align="right" valign="top">
- 09: <img src="img/t1.png" alt="Gallery" width="194" height="60">
- 10: </td>
- 11: </tr>
- 12: </tbody></table>
見出しは見出し要素 h1 や h2 を使ってマークアップし直します。
- 01: <h1><img src="img/t1.png" width="194" height="60" alt="Gallery" /></h1>
- 02: <h2><img src="img/t2.png" width="251" height="39" alt="Original" /></h2>
テーブル内の右上に配置された画像をh1、左下に配置された画像をh2としました。
本文(画像)
- 01: <table border="0" align="center" cellpadding="0" cellspacing="0" summary="本文">
- 02: <tbody><tr>
- 03: <td align="center"><br>
- 04: <table bgcolor="#aaeeff" border="10" cellpadding="0" cellspacing="0" summary="画像">
- 05: <tbody><tr>
- 06: <td>
- 07: <img src="http://mimi.moe.in/j/akrj15.jpg" width="302" height="437" alt="かぼちゃ">
- 08: </td>
- 09: </tr></tbody>
- 10: </table>
- 11: </td>
- 12: </tr></tbody>
- 13: </table>
テーブルで枠をつけたりセンタリングしているので、HTMLからこれを取り除きます。
- 01: <p class="pict"><img src="http://mimi.moe.in/j/akrj15.jpg" width="302" height="437" alt="かぼちゃ" /></p>
img要素はbody要素直下に置けないのでp要素の中に入れます。そしてあとでCSSでレイアウトするためにclass属性pictをつけておきます。class属性の名前は適当ですが、中に画像を入れているという意味でpictとしました。
本文(説明文)
- 01: <table width="85%" border="0" align="center" cellpadding="0" cellspacing="0" summary="絵の説明の外枠">
- 02: <tbody><tr>
- 03: <td><img src="img/blank.png" alt="" width="1" height="10"></td>
- 04: </tr>
- 05: <tr>
- 06: <td><img src="img/kado-ul.png" width="59" height="59" alt=""></td>
- 07: <td></td>
- 08: <td align="right"><img src="img/kado-ur.png" width="59" height="59" alt=""></td>
- 09: </tr>
- 10: <tr align="center">
- 11: <td></td>
- 12: <td bgcolor="#ffffff">
- 13: <table width="95%" border="0" cellpadding="0" cellspacing="0" summary="絵の説明">
- 14: <tbody><tr>
- 15: <td><img src="img/blank.png" alt="" width="1" height="10"></td>
- 16: </tr>
- 17: <tr>
- 18: <td>タイトル</td><td>カボチャ祭り</td>
- 19: </tr>
- 20: <tr>
- 21: <td colspan="2"><hr></td>
- 22: </tr>
- 23: <tr>
- 24: <td> 作者</td><td>あきら☆M</td>
- 25: </tr>
- 26: <tr><td colspan="2"><hr></td>
- 27: </tr>
- 28: <tr>
- 29: <td width="64" valign="top"> コメント</td><td>カボチャを食べよう、食べないとイタズラするぞー、とゆーお祭りだったっけ? (違います)</td>
- 30: </tr>
- 31: <tr><td colspan="2"><hr></td>
- 32: </tr>
- 33: <tr>
- 34: <td> 制作日</td><td>2003.11.02.(Sun)</td>
- 35: </tr>
- 36: <tr>
- 37: <td><img src="img/blank.png" alt="" width="1" height="10"></td>
- 38: </tr></tbody>
- 39: </table>
- 40: </td>
- 41: </tr>
- 42: <tr>
- 43: <td><img src="img/kado-dl.png" width="59" height="59" alt=""></td>
- 44: <td></td>
- 45: <td align="right"><img src="img/kado-dr.png" width="59" height="59" alt=""></td>
- 46: </tr>
- 47: </tbody></table>
テーブルで組んだ説明文の四隅に飾り罫の画像がこれまたテーブルで配置されています。要するにテーブルが入れ子で使われています。
この飾り罫画像は明らかに装飾なのでCSSにまかせてHTMLからなくしたいのですが、なかなかむずかしいところです。それで今回は飾り罫をHTMLに残すことにしました。
- 01: <div class="comment">
- 02: <p class="comment-decoration">
- 03: <img src="img/kado-ul.png" width="59" height="59" alt="" />
- 04: <img class="decoright" src="img/kado-ur.png" width="59" height="59" alt="" />
- 05: </p>
- 06: <dl>
- 07: <dt>タイトル</dt><dd class="title">カボチャ祭り</dd>
- 08: <dt>作者</dt><dd>あきら☆M</dd>
- 09: <dt>コメント</dt><dd>カボチャを食べよう、食べないとイタズラするぞー、とゆーお祭りだったっけ? (違います)</dd>
- 10: <dt>制作日</dt><dd>2003.11.02.(Sun)</dd>
- 11: </dl>
- 12: <p class="comment-decoration">
- 13: <img src="img/kado-dl.png" width="59" height="59" alt="" />
- 14: <img class="decoright" src="img/kado-dr.png" width="59" height="59" alt="" />
- 15: </p>
- 16: </div>
まず、上の左右の飾り罫、説明文、下の左右の飾り罫と3つの部分に分け、div要素の中に入れてます。 飾り罫画像は p要素に入れました。 ここでの説明文はきちんと表の形になっているのでテーブルのままでもよいのですが、今回はdl要素(定義リスト)としてマークアップし直してみました。
フッタ
- 01: <table width="100%" border="0" align="center" cellpadding="0" cellspacing="0" summary="フッタ">
- 02: <tbody><tr>
- 03: <td valign="top">
- 04: <img src="img/blank.png" alt="" width="20" height="5"><a href="tab2css2.html">もどる</a>
- 05: </td>
- 06: <td align="right">
- 07: <font size="-2">2004.03.08.</font>
- 08: <img src="img/banner.jpg" alt="footer" width="181" height="40">
- 09: </td>
- 10: </tr></tbody>
- 11: </table>
フッタは他のページへのナビゲーションと日付、バナーがあります。ここではナビゲーションは p要素、日付とバナーは address要素でマークアップします。
- 01: <div class="footer">
- 02: <p><a href="tab2css2.html">もどる</a></p>
- 03: <address>2004.03.08.
- 04: <img src="img/banner.jpg" alt="footer" width="181" height="40" />
- 05: </address>
- 06: </div>
これで表示部分の書き直しは完了です。見栄えに関する指定を取り去ったので、短く簡潔になりました。
head
さて最後になりましたが、文書先頭のhead要素まわりを書き換えます。
- 01: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- 02: "http://www.w3.org/TR/html4/loose.dtd">
- 03: <html lang="ja">
- 04: <head>
- 05: <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
- 06: <title>tableレイアウトの例</title>
- 07: </head>
- 08: <body background="img/bg3.png" bgcolor="#ffffff" text="#444444" link="#3377cc" vlink="#9933cc" alink="#ff4433">
HTML4.01 Transitional から XHTML1.1 にしたのでDOCTYPE宣言をXHTML1.1のものに変え、XML宣言を先頭に追加します。
- 01: <?xml version="1.0" encoding="Shift_JIS"?>
- 02: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
- 03: "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
- 04: <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
- 05: <head>
- 06: <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" />
- 07: <title>CSSレイアウトの例</title>
- 08: <link rel="stylesheet" type="text/css" href="tab2css2-2.css" />
- 09: </head>
- 10: <body>
DOCTYPE宣言とは、この文書がどのバージョンのHTMLで書かれているかを示すもので必須(必ず書かなければならない)のものです。現在よく使われているブラウザではDOCTYPE宣言を見てレンダリングモードを変えています(DOCTYPEによって表示結果が違うことがあります)。
それからlink要素でCSSファイルを指定します。(8行目)
CSSでの指定
さて、HTMLから追い出した見栄えの指定をCSSで表現してやります。→CSSファイルを直接見る
全体
背景色や文字の色などbody要素に指定してあったものをCSSで指定します。
- 01: body {
- 02: background : #fff url(img/bg3.png);
- 03: color: #444;
- 04: margin: 0; padding:0;
- 05: }
- 06: a { text-decoration: underline; }
- 07: a:link { color:#37c; }
- 08: a:visited { color:#93c;}
- 09: a:active, a:link:hover , a:visited:hover { color:#f43; }
せっかくなのでプラスアルファもしてます。4行目のマージンとパディングは
見出し
"Gallery"の画像(h1要素)を右上に、"Original"の画像(h2要素)を左に配置します。
- 01: h1 {
- 02: margin: 0; padding: 0;
- 03: text-align: right;
- 04: }
- 05: h2 { margin: -30px 0 15px 15px; padding: 0 }
本文(画像)
センタリングした上で画像のまわりに枠をつけるのですから、img要素の親でブロックレベル要素であるp要素にセンタリングの指定、img要素にボーダーの指定をします。
- 01: p.pict {
- 02: margin: 0 0 10px 0; padding:0;
- 03: text-align: center;
- 04: }
- 05: p.pict img {
- 06: margin: 0; padding:5px;
- 07: background: #dee;
- 08: border: solid 10px;
- 09: border-color : #eff #9bb #add #dff;
- 10: }
さて、ここではテーブルでの枠の指定をそのままCSSに移してません。そのまま移すならば8,9行目はこうです。
- border: outset 10px #cef;
CSSでもテーブルでの指定でもそうなのですが、枠線(border)の立体表示ではブラウザによって色が違います(→参考:各ブラウザでのボーダーの違い)。それで四辺それぞれに直接色を指定するようにしました。(ついでに色自体も水色に変えてます)
本文(説明文)
HTMLの書き直しでこの部分は上の飾り罫、説明文、下の飾り罫の3つに分割しました。まず飾り罫部分です。これは上下とも同じ設定です。
- 01: div.comment { margin: 0 7.5%; padding: 0; }
- 02: p.comment-decoration {
- 03: margin: 0; padding: 0;
- 04: position: relative;
- 05: }
- 06: img.decoright {
- 07: position: absolute;
- 08: top: 0; right: 0;
- 09: }
もとのtableでは、width="85%" align="center" となってました。それに対応するのが、説明文部分を囲むdiv要素への指定である1行目の margin: 0 7.5%; padding: 0; です。左右のマージンにそれぞれ7.5%を指定しているので、残った部分は85%となります(パディングが0なので)。また、飾り罫を入れたp要素を、中の画像の絶対位置決めの基準(包含ブロックといいます)とするために position: relative;と指定しています。
そして7,8行目が右の飾り罫画像への指定です。7行目で絶対位置決めの指定をして、8行目で包含ブロックからのオフセットを指定しています。「上から0、右から0」ですので、包含ブロックの右上に寄せることになります。この場合は、このp要素内には2つの同じ高さの画像だけしかありませんので(p要素の高さ=画像の高さ)、「右下に寄せる」指定をしても同じ結果になります。
- 01: div.comment dl {
- 02: background: #fff;
- 03: margin: -20px 39px; padding: 0.3em 1em;
- 04: line-height: 1.4;
- 05: }
- 06: div.comment dt {
- 07: margin: 0; padding: 0.3em 0;
- 08: width: 4.5em;
- 09: color: #559;
- 10: }
- 11: div.comment dd {
- 12: margin: -2.1em 0 0 0; padding: 0.3em 0 0.4em 5em;
- 13: border-top: 0.1em solid #bbc;
- 14: }
- 15: div.comment .title { border-top: 0; }
それでは説明文部分です。ここでは定義リストとしてマークアップしてます。これはとくにスタイル指定してなければ次のように表示されます。
これをdt要素とdd要素が横に並ぶように表示します。まず、ここではdt要素の文字が最大4文字なので、dd要素の左側の空きをパディングで5文字分確保します(左側のマージンは0。これは後で説明するボーダーの都合です)。そして上マージンにマイナスの値を指定してdt要素と並ぶようにしてやるのですが、さて、どれだけマイナスしてやればいいのでしょうか。
ではddの上マージンが0の時、dt要素とdd要素の距離を計算してみましょう。ここでは行の高さの中心を基準にして考えます。
[dtの行の高さの下半分]+[dtの下パディング]+[dtの下ボーダー]+[dtの下マージンとddの上マージン]+[ddの上ボーダー]+[ddの上パディング]+[ddの行の高さの上半分]
隣り合うマージンは相殺するのでちょっとややこしいのですが、ここでは両方0とします(片方が0であれば相殺を考える必要はありません)。行の高さは "line-height: 1.4"、dtの下パディングとddの上パディングはそれぞれ 0.3em を指定するとします。また、dtにはボーダーはなし、ddには上に0.1em幅のボーダーをつけることにします。そうするとこうなります。
0.7em + 0.3em + 0 + 0 + 0.1em + 0.3em + 0.7em = 2.1em
すべて em で指定してあるのがミソです。ここでの line-height は倍率での指定ですが、そのままemに換算できます。また行の高さは上下に均等に割り振られます。
これで縦の距離が計算できたので、これのマイナス値をddの上マージンに指定してdtと並ぶようにします。(パディングにはマイナス指定はできません)
さて、元のテーブルでは項目の間に水平罫線(hr要素)で線を引いていました。こちらではボーダーで表示させます。dt要素とdd要素それぞれにボーダーをつけると、上下方向にズレがでることがあります(ブラウザ側の文字の大きさの設定によってズレたりズレなかったりします)。それでボーダーはdd要素だけにして、これでdt要素の分までカバーすることにします。
さきほどdd要素の左側の空きをパディングで指定したのはこのためです。マージンはボーダーの外側部分、パディングはボーダーの内側部分の空きの指定です。
また、dl要素(定義リスト要素)のマージンを調整して飾り罫画像とのスペースを調整します(3行目)。テーブルで組んだときのレイアウトではちょっと間が開きすぎてると感じたので、少しつめてみました。
マージン・パディングを使えばスペースを確保するための透明画像はもう不要です。 マイナスのマージンを活用すれば、要素を重ねることもできますし、さらに position: absolute を使えばどこへでも配置できます。
フッタ
- 01: hr { display: none; }
- 02: div.footer {
- 03: margin: 1em 0 0 0; padding: 0.5em;
- 04: border-top: 2px solid #bbc;
- 05: }
- 06: div.footer p { margin: 0; padding: 0; }
- 07: div.footer address {
- 08: margin: -1.25em 0 0 0; padding: 0;
- 09: text-align: right;
- 10: font: 80% "Georgia","Times New Roman",serif ;
- 11: }
hr要素はブラウザによってCSSの指定の結果の差が大きいので、非表示にして(1行目)、代わりにフッタ部分を囲っているdiv要素にボーダーをつけます(4行目)。(とくに変わった指定はしていませんけどね)
まとめ
テーブルを使ったレイアウトをCSSでのレイアウトに書き直すときに一番大切なのは、HTMLをシンプルに(もっといえば文書の構造を論理的に)改めることだと思います。あとあと内容の修正・更新が楽になると思いますし、デザインの変更も楽です。