CSSでレイアウト

Web ページのレイアウトは、よくテーブルが使われてきました。現在は少なくなりましたが、まだ一部で使われています。新聞、雑誌記事のように格子状に分割し文章や画像を貼り付ける方法です。 いわゆる「段組」です。自由に複雑な段組ができます。代表的なブラウザは、テーブルレイアウトで作成された Web ページの表示に違いがでることはほとんどないのですが、 HTML ソースは複雑になりメンテナンスが難しく、標準仕様を策定している W3C では「アクセシビリティ」という点でテーブルレイアウトは推奨していません。アクセシビリティとは、様々な利用環境に配慮することで、例えば、テキストブラウザ、音声読み上げブラウザ、モバイルなどです。CSS によるレイアウトを推奨しています。

現在は、高機能でマルチスクリーン、レスポンシブに対応できる、新バージョン CSS3 の「マルチカラムレイアウト」や、「フレキシブルボックスレイアウト」が使えるようになりました。「新しい CSS レイアウトモジュール」を参考にしてください。(2015年 2月)

難しい CSS でレイアウト

CSS で段組を実現するには、<div> 要素でボックス化し、プロパティ positionfloatが主に使われてきました。width、right、left、top、clear といった他のプロパティと組み合わせ、「積み木を積み重ねる」という感覚でレイアウトします。

ここでは、これからも使われる position、float プロパティと、display: table を記述しています。


position プロパティ

position プロパティは、ボックスの配置位置を決めるためのボックスの配置方法を指定します。指定できる値には、static、relative、absolute、fixed があります。

static (静的配置)

position プロパティを指示しない通常の配置方法と同じになります。つまり、ブロックレベル要素(p、div など)の場合、親ボックスの最上部から順に下に 配置されていきます。インライン要素(em、span など)は、行ボックスの中で水平方向に左から右に順に配置されます。特に position プロパティを指定しないときは、 static が初期値として選択されています。

relative (相対配置)

left: 30px; top: 20px;
static
relative
static

static と同じように、上から下に通常の配置に従いますが、最上位の左側が基準になり相対的に、left 、top などのプロパティを併用してずらして配置する相対配置です。

右に 30px(left: 30px;)、下に 20px (top: 20px;) 位置をずらした例です。後続のボックスは relative のボックスが本来配置されるはずだった位置 にあるものとして配置されます。

.box-B {
  position: relative;
  left: 30px;
  top: 20px;
}

上記の使用例の他に、よく次の絶対配置の基準点をつくるために、親要素として relative 配置をする使われ方をします。

absolute (絶対配置)

static
absolute
left: 35px; top: 25px;

absolute は、position プロパティを使って段組を作る場合に、基準になるボックスとして重要な役割を担います。

図は、ボックスを表示画面として画面のパディング左上を基準点として右に 35px、下に 25px の位置に絶対配置している例です。

.box-B {
  position: absolute;
  left: 35px;
  top: 25px;
}

absolute を指定したボックスの親ボックスとなるのは、static 以外の値が指定されているボックスです。もし、親ボックスが ない場合は、画面の表示領域が配置の基準点になります。配置位置は、親ボックスを基点として、top、left、right、bottom などの プロパティを用いて配置する絶対配置です。

absolute 指定のボックスは、通常の配置とは独立して扱われます。例えば、配置したところに他のボックスなどがあってもそのまま 重なって表示されます。

fixed (固定配置)

この値を指定したボックスは、absolute を指定したときと同じ仕組みで配置されます。absolute と異なる点は、配置位置が画面表示領域に対して固定されます。 従って、画面のスクロールバーでスクロールしても、常に同じ位置に表示され固定されます。

Top↑

float プロパティ

float プロパティは、ボックスを左、または右に寄せて配置させ、後続の内容は float プロパティで指定した方向と反対方向に回り込むように配置されます。

  1. フロートボックスは、その外辺が包含ブロックもしくは他のフロートボックスの外辺に接するまで左(右へなら右)に移動します。
  2. 行ボックスがある場合、フロートボックスの上外辺は行ボックスの上辺に合わされます。
  3. 先行する他のフロートボックスがあって余白が不足する場合は、フロートボックスは下に移動して配置されます。いわゆるカラム落ちです。

float: left; (左寄せ)

【HTML】
<div class="box-A">ボックスA</div>
<div class="box-B">ボックスB</div>
【CSS 】
.box-A {
  float: left;
  width: 100px;
  height: 70px; 
  background-color: #cff;
}
.box-B {
  float: left;
  width: 150px;
  background-color: #fcf;
}

ボックスA

float:left;

ボックスB
float プロパティの後続ボックスの内容は、float 指定した方向と反対方向に回り込みます。

float: right; (右寄せ)

CSS は次のように、left → right に変わっただけです。

【CSS 】
.box-A {
  float: right;
  width: 100px;
  height: 70px;
  background-color: #cff;
}
.box-B {
  float: right;
  width: 150px;
  background-color: #fcf;
}

ボックスA

float:right;

ボックスB
float プロパティの後続ボックスの内容は、float 指定した方向と反対方向に回り込みます。

Top↑

フロート配置の表示とマージン

画像が含まれる2行のテキスト図

フロート配置は、フロートしたボックスの周囲に後続の行ボックスの文章を回り込ませる形でよく使われます。通常フローから外れ、文字通り浮いている状態になるので隣接ボックスとのマージン、表示のしかたが通常フローと異なってきます。

図のような2行の行ボックスで構成され、1行目の文章中に画像が入った通常フローのサンプルで、画像を左フロート配置しマージンや表示のしかたがどのようになるかを確認してみます。

【HTML】
<div class="parent">
<p class="p1">フロートボックスは、その外辺が・・(省略)・・外辺に接するまで
<img alt="勿忘草" src="./img/forget.gif">左(右へなら右)に・・</p>

<p class="p2">行ボックスがある場合は、フロートボックスの・・(省略)</p>
</div>
【CSS 】
.parent {
  width: 280px;
}
.parent img {
  width: 100px;
  height: 80px;
  margin: 0;
  padding: 0;
  vertical-align: baseline;/* 通常フローの初期値で省略可 */
}
p {
  margin: 0;
  padding: 0;
  line-height: 100%;
}
.p1 {
  background-color: #eee;
  border: 2px dashed blue; /* 外枠を目立つように */
}
.p2 {
  background-color: #ffc;
  border: 2px dashed purple;/* 外枠を目立つように */
}

1.画像を左フロート (float:left; margin: 0

画像を左フロートした図

画像を左フロート配置すると、画像は行ボックスから外れ、同じ行ボックスの左下に移動し、直前のインラインボックスの「するまで」は、右に回り込んで以降の行ボックスの幅が短くなります。 IE7、Firefox2 以前は、後続の行ボックスの前に移動し、その行ボックスは幅が短くなって右に回り込みます。

.parent img {
  float: left;
  margin: 0;
  width: 100px;
  height: 80px;
  padding: 0;
}
Memo
  • フロートされたボックスは通常フローから外れる。
  • フロートされたボックスを子孫にもつ親ボックスは、フロートボックスの高さを含めない。

2.画像をフロート、両方の行ボックスにマージン ( margin: 1em

画像をフロート、行ボックスにマージン 1em

両方の行ボックスにマージン1em 指定すると、フロートボックスとの間にはとれません。行ボックス同士のマージンになります。フロートボックスは通常フローから外れて浮いている状態を確認できます。

行ボックス間の上下マージンは、1em + 1em = 2em とはならず 1em になります。これは通常フローボックス間の「マージンの相殺」といいます。

Memo
  • フロート解除しない後続ボックスの上マージンは、先行するフロートボックスではなく、その親ボックスとのマージンとして働く。

3.フロート画像にマージン ( margin: 1em

フロート画像にマージン 1em

フロートボックスの画像にマージン 1em 指定すると、隣接する行ボックス内部のインラインボックスとの間にマージン 1em がとれます。


.parent img {
  float: left;
  width: 100px;
  height: 80px;
  margin: 1em;
  padding: 0;
}
Memo
  • フロートボックスで指定したマージンは、フロート解除しない行ボックスとは機能せず、行ボックス内のインラインボックスとの間で機能する。

Top↑

4.インラインボックスに負のマージン ( margin-left: -2em

インラインボックスに負のマージン -2em

行ボックス内部をインラインタグ<strong>で抽出したインラインテキスト、「行ボックス」部分に負のマージン -2em を指定すると、フロートボックスに重なり上書きされます。 但し、IE7以前のブラウザはフロートボックスの下に隠れます。


<p class="p2">
  <strong style="margin-left: -2em; color: red;
  border: 2px solid red;">行ボックス</strong>がある場合は・・
</p>
Memo
  • 行ボックス内のインラインボックスはフロートボックスの前面に、ブロックは背面に描画される。

5.インラインボックスをフロート配置 ( float: left; margin: 1em

インラインボックスをフロート配置

前記に続き、インラインボックスのテキスト、「行ボックス」部分をフロート配置し、マージン 1em を指定すると上下左右のマージンがとれブロックボックスに変化します。

もともと画像もインライン要素ですが、幅、高さが決まっているので置換要素といわれています。


<p class="p2">
  <strong style="float: left; margin: 1em; color: red; 
  border: 2px solid red;">行ボックス</strong>がある場合は・・
</p>
Memo
  • インラインボックスをフロートすると、ブロックボックスになる。

Top↑

6.後続の行ボックスのフロート解除 ( clear: left; margin: 1em

後続の行ボックスのフロート解除、マージン 1em

後続の行ボックスに clear: left 指定で、右側への回り込みが解除されます。マージンは解除前と同じように先行の行ボックスとのマージンになります。この例ではクリアランスが自動的にとられ フロートボックスの下に配置されたので、クリアランス分以上のマージン値でないと効きません。

先行の行ボックスの高さは、フロートボックスの高さを含めないので、行ボックス内のインラインボックスを囲む高さしかありません。背景や枠(ボーダー)などフロートボックスを含めたい場合は、float 化か、 overflow プロパティによって拡張できます。(後述)

.p2 {
  clear: left;
  margin: 1em;
  background-color: #ffc;
  border: 2px dashed purple;
}
Memo
  • フロート直下の行ボックスは、フロート解除すると回り込みが解除されフロートボックスの下に配置される。
  • フロート解除しても後続行ボックスの上マージンは、先行するフロートボックスとの間には機能しない。

7.後続の行ボックスの上マージン ( clear: left; margin-top: 4em

後続の行ボックスの上マージン 4em

フロートボックスの下マージンを後続の行ボックスの上マージン margin-top でとる場合は、前述のように先行の行ボックス間とのマージンを指定することになります。 IE7 以前はフロートボックス間のマージンになり、Firefox2 以前は無視され効かないなど、ブラウザにより異なりました。

後続の行ボックスの上マージンは、先行フロートボックスの下マージン margin-bottom でとるほうが確実で適しています。

.p2 {
  clear: left;
  margin-top: 4em;
  background-color: #ffc;
  border: 2px dashed purple;
}
Memo
  • フロート解除しても後続の行ボックスの上マージンは、先行するフロートボックスの親ボックスとのマージンとして働く。
  • フロートボックスとフロート解除した後続の行ボックスとのマージンは、フロートボックス側の下マージン margin-bottom で指定する。

8.先行の行ボックスに overflow 、後続のボックス margin: 1em

先行の行ボックスに overflow 、後続のボックスにマージン

フロートボックスを子孫にもつ親ボックスは、フロートボックスの高さを計算しないのですが、overflow プロパティの値 visible 以外のauto、scroll、hidden によって高さを認識できるようになり親ボックスの高さが拡張されます。 従って、親ボックス側でのフロート解除する手段として使われます。auto、scroll はスクロールバーが表示される場合があるので hidden が適しています。


.p1 {
  overflow: hidden;
  background-color: #eee;
  border: 2px dashed blue;
}
.p2 {
  margin: 1em;
  background-color: #ffc;
  border: 2px dashed purple;
}
Memo
  • フロートボックスを子孫にもつ親ブロックボックス側に overflow: hidden プロパティ指定することで、後続ボックスのフロートを解除し、フロートボックスの高さを含められる。

9.後続の行ボックスに overflow: hidden;

後続の行ボックスに overflow: hidden

後続のボックスに overflow: hidden を指定すると、図のように先行ボックスのフロートボックスの高さを越えてもフロートボックスの下に回り込みません。回り込ませたくない場合に使えます。


.parent img {
  float: left;
  width: 100px;
  height: 80px;
}
.p2 {
  overflow: hidden;
  margin: 0;
  background-color: #ffc;
  border: 2px dashed purple;
}

付記

Top↑

フロートの解除 clearoverflow:hidden プロパティ

clear プロパティ

float プロパティの、「回り込みの解除」としてブロックレベル要素に適用されます。

【 プロパティ値 】
  • clear: left;   左側フロート要素の回り込み解除
  • clear: right; 右側フロート要素の回り込み解除
  • clear: both;   両側すべてのフロート要素の回り込み解除

clear プロパティの指定例 】
  1. 適用したいボックスのCSS に直接指定する。
    (例 1 )セレクタに指定
    #footer { clear: both; --- ; }
    (例 2 )HTML 要素に指定
    <p style="clear: both;">フロートの回り込み解除・・・</p>
  2. 改行要素<br>の属性として適用したいところで指定する。
    (例) <br style= "clear: both;">
  3. フロートクリア用セレクタをつくり、要素のクラスセレクタとして指定する。
    (例) .clearfloat { clear: both; }
    <br class= "clearfloat">
    <div id="column" class="clearfloat"></div>

clear プロパティは、ブロック要素だけでインライン要素には使えませんが、br 要素だけはインライン要素でも使えるようです。

親要素でフロート解除 overflow: hidden

clear プロパティは、フロートボックスの後続ボックス側で使用しますが、親要素側で指定したいときには、overflow:hidden を使います。(前記サンプル) 但し、IE6以前のブラウザは機能しません。

他に、親要素側でクリアする「clearfix」というセレクタがネット上でいろいろ公開されています。機能をよく確認して利用できます。

float を使用するときの注意点
  • float プロパティには、width 指定は必須。
  • clear した要素には上マージンを指定しない。先行フロートボックス側で下マージンを指定する。

Top↑

CSS テーブルレイアウトdisplay: table

table 要素に対して、IE8 からデフォルトスタイルシートが以下のように定義されました。これらを任意の要素に指定することで、table 要素 と同じようなレイアウトにすることができます。CSS にしても HTML のドキュメント構造と表示を分離することは難しいので アクセシビリティに影響のない範囲で利用できます。

【 table 要素のデフォルトスタイルシート 】

table    { display: table }
tr       { display: table-row }
thead    { display: table-header-group }
tbody    { display: table-row-group }
tfoot    { display: table-footer-group }
col      { display: table-column }
colgroup { display: table-column-group }
td, th   { display: table-cell }
caption  { display: table-caption }

要素を均等に横並びにする例display: table-cell

要素を横並びにするには、floatdisplay: inline-block、CSS3 の display: flex やマルチカラムレイアウト columns:* などがありますが、display: table-cell でも同じようなことができます。 テーブル要素のtd、th と同じふるまいになるので、「要素を均等に配置できる」のと、「要素内の上下中央揃え」が容易になります。次のリストボックスを横並びにするメニューの例で説明します。

親要素に display: table を、子要素に display: table-cell を指定するだけで横並びになります。複数段(行)になる場合は、table と同じように tr 要素のdisplay: table-row; で囲みます。 一行のときは、tr 要素があるものとしてレンダリングされるので省略できます。要素を均等に並べるために親要素には、table-layout: fixed; を指定し固定幅にします。このときテーブル全体の幅指定 width: は必須です。 ボックス幅をセル内容に応じて均等にしない場合は、table-layout: auto; にします。これは初期値なので省略できます。下図はサンプルです。

要素を均等に横並びにする CSS テーブルレイアウト例
【HTML】
<ul class="menu">
  <li><a href="#">menu-1</a></li>
  <li><a href="#">menu-222</a></li>
  <li><a href="#">menu-33</a></li>
  <li><a href="#">menu-4</a></li>
  <li><a href="#">menu-555</a></li>
</ul>
【CSS 】
ul.menu {
  display: table;          /* 親要素に指定 */
  table-layout: fixed;     /* 固定レイアウト */
  width: 100%;             /* 幅指定は必須 */
  padding: 0;
}
ul.menu li {
  display: table-cell;    /* 子要素のセル指定 */
  text-align: center;
  background-color: #393;
  border-left: 1px solid #fff;/* ボックス境目の縦線 */
}
ul.menu li:first-child {
  border: none;    
}
ul.menu li a {
  display: block;
  text-decoration: none;
  color: #fff;
  padding: 3px;
} 
ul.menu li a:hover {
  display: block;
  background-color: #fc0;
  color: #fff;
}

間隔を空けて要素を均等に横並びにする例

上記のサンプルで間隔を空けて均等に横並びにするには、セル td を使って横並びにしているので、セルボックス間の margin は機能しません。内側の padding だけ機能します。そのためテーブルのボーダー(外枠線や内側罫線)の表示を設定する border-collapse:* を使用します。プロパティ値を、「separate 」にして、border-spacing:* プロパティで間隔を指定します。border-spacing:* プロパティ値が1つの場合は、 上下左右に同じ間隔が適用され、2つを半角スペースで区切った場合は、前の値が「左右」、後の値は「上下」の間隔になります。

下記の例の border-spacing: 10px 0; は、左右の隣接間隔が "10px" に、上下が "0" なります。通常のマージンとは異なります。

間隔を空けて要素を均等に横並びにする CSS テーブルレイアウト例
【CSS 】
ul.menu {
  display: table;
  table-layout: fixed;
  width: 100%;
  padding: 0;
  border-collapse: separate; /* ボーダーを分離して表示 */
  border-spacing: 10px 0;    /* 左右 10px、上下 0px */
}

セル要素内のボックス中央揃えが容易

テーブルセル内の位置揃えを設定する td 属性には水平方向の align、垂直方向の valign 属性があり、上下左右中央揃えができます。これを CSS で設定する場合は、 通常はブロック要素に適用する水平方向の text-align プロパティと、インライン要素に適用する垂直方向の vertical-align プロパティがセル要素内ではどちらも適用します。 従って、ボックス内の中央揃えは、子要素セルに 水平方向 text-align: center; 垂直方向 vertical-align: middle; の指定で下図サンプルのように簡単にボックス中央配置ができます。(画像クリックで他のサンプルも表示)

セル要素内のボックス中央揃えサンプル
【CSS 】
ul.main {
  display: table;
  table-layout: fixed;
  width: 100%;
  padding: 0;
}
ul.main li {
  display: table-cell; /* 子要素セルに設定 */
  height: 150px;
  text-align: center;     /* 水平方向位置 */
  vertical-align: middle; /* 垂直方向位置 */
  border: 1px dotted gray;
  color: blue;
}

セル要素内の配置は下表のプロパティ値を組合せて行います。vertical-align は4種類だけです。他に text-top、text-bottom、sub、super がありますが適用しません。

【セル要素内の配置プロパティ】
プロパティ プロパティ値 説 明
text-align
(水平方向)
left 左寄せ(初期値)
center 中央寄せ
right 右寄せ
vertical-align
(垂直方向)
baseline セルのベースラインを行のベースラインに揃える(初期値)
top 上寄せ
middle 中央寄せ
bottom 下寄せ

Memo
  • 通常配置では難しいボックス内の中央揃え、下揃えが比較的容易にできる。
  • ボックスを均等幅、均等高さに容易に並べられる。
  • テーブル要素内の、position プロパティ値 relative、absolute は基準点を特定できないので適用しない。
  • テーブル要素のセルの連結 rowspan、colspan という機能はないので、セルを連結した複雑なテーブルは、HTML の場合よりも更に複雑になる。
  • display: table-cell によるレイアウトは可変幅のリキッドタイプにできるので、マルチスクリーン、レスポンシブにある程度対応できる。CSS3 の「マルチカラムレイアウト」や「フレキシブルボックスレイアウト」のような柔軟性はない。

関連記事

Top↑