CSSで2カラムを作ってみる
CSSで2カラムといっても、その作成方法は様々です。
多くのパターンを理解することは、CSSに柔軟性を持たせることに、つながります。
1. floatを利用する
基本的な方法です。
子にfloatを利用すると、灰色の背景を敷いている親の高さが算出できなくなるため、背景色が出なくなったり、レイアウトが崩れたりします。
これらの問題を解決するには、clearfix か overflowを利用する必要があります。
.parent {
overflow: hidden;
}
.child1 {
float: left;
width: 240px;
}
.child2 {
float: right;
width: 128px;
}
2. floatとmarginを一定方向にかける
片方にfloat、片方はfloatをかけた方向に隣の要素の横幅以上のmarginをとる方法です。
floatのかかっている数値は固定して、文字の部分を伸縮させる時などに非常に効果的です。
この方法を利用すると、floatのかかっていないボックスの高さに依存して、親の高さがとれます。
そのため場合によっては、floatを解除しなくても、レイアウトを崩さずにコーディングすることも可能です。
.child1 {
float: left;
width: 240px;
}
.p-child2 {
margin-left: 256px;
}
3. floatと隣接のボックスにoverflow: hidden;をかける
上記の方法だとmarginに数値を設定する必要があるため、より柔軟にするためにoverflowを利用します。
overflowを利用すると、書式コンテキストが確立するため、回り込みが起こらずに2カラムを実現することができます。
レイアウトに、より柔軟性を持たせたい時に有効な手法です。
.child1 {
float: left;
width: 240px;
margin-right: 16px;
}
.p-child2 {
overflow: hidden;
}
4. floatとマイナスマージン
親のボックスが400pxで、子のボックスに幅190pxとmargin 20pxが指定されている場合。
(190+20)*2 = 420
全体幅が420pxとなり、400pxの親のボックスよりも大きくなるため、通常ならカラム落ちが発生します。
しかしマイナスマージンを加えることで、IE8以上であればカラム落ちを防げます。
.parent {
overflow: hidden;
margin-right: -20px;
}
.child1,
.child2 {
float: left;
width: 190px;
margin-right: 20px;
}
この方法は2カラムだけに限定するよりも、数カラムになっているリストなどにも役立つ方法です。
このパターンは、よく使えるわりに計算が面倒くさいので、Preprocessorのmixinなどを利用すると計算が必要なくなります。
SCSS, Sass, Less, Stylus の例
SCSS
@mixin layout-pattern($areaWidth, $colNum, $colGap, $childEl: li, $legacy: false) {
// layout-pattern(親の横幅, カラム数, カラムの間隔, 子のセレクタ, IE7以下に対応する?(デフォルトは、対応しない))
$colAreaWidth: $areaWidth + $colGap;
overflow: hidden;
margin-right: -#{$colGap};
@if $legacy {
width: $colAreaWidth;
zoom: 1;
}
#{$childEl} {
float: left;
$colWidth: $colAreaWidth / $colNum - $colGap;
width: floor($colWidth);
margin-right: $colGap;
@content;
}
}
ul {
@include layout-pattern(400px, 5, 8px)
}
.test {
@include layout-pattern(400px, 4, 16px, ".col") {
border: 1px solid #000;
margin-bottom: 20px;
box-sizing: border-box;
}
}
Sass
=layout-pattern($areaWidth, $colNum, $colGap, $childEl: li, $legacy: false)
// layout-pattern(親の横幅, カラム数, カラムの間隔, 子のセレクタ, IE7以下に対応する?(デフォルトは、対応しない))
$colAreaWidth: $areaWidth + $colGap
margin-right: -#{$colGap}
overflow: hidden
@if $legacy
width: $colAreaWidth
zoom: 1
#{$childEl}
$colWidth: $colAreaWidth / $colNum - $colGap
float: left
width: floor($colWidth)
margin-right: $colGap
@content
ul
@include layout-pattern(400px, 5, 8px)
.test
@include layout-pattern(400px, 4, 16px, ".col")
border: 1px solid #000
margin-bottom: 20px
box-sizing: border-box
Less
// もう少しブラッシュアップしたい
.layout-legacy(@legacy-width) when (@legacy) {
width: @legacy-width;
zoom: 1;
}
.layout-pattern(@areaWidth, @colNum, @colGap, @childEl: li, @legacy: false) {
// layout-pattern(親の横幅, カラム数, カラムの間隔, 子のセレクタ, IE7以下に対応する?(デフォルトは、対応しない))
@colAreaWidth: @areaWidth + @colGap;
overflow: hidden;
margin-right: -@colGap;
.layout-legacy(@colAreaWidth);
@{childEl} {
float: left;
@colWidth: @colAreaWidth / @colNum - @colGap;
width: floor(@colWidth);
margin-right: @colGap;
.child-content();
}
}
ul {
.child-content() {}
.layout-pattern(400px, 5, 8px);
}
.test {
@childEl: .col;
.child-content() {
border: 1px solid #000;
margin-bottom: 20px;
box-sizing: border-box;
};
.layout-pattern(400px, 4, 16px, @childEl);
}
stylus
browserLegacy = false; // IE6, 7に対応するか
layout-pattern(var)
colAreaWidth = var[0] + var[2]
overflow hidden
margin-right -1 * var[2]
if browserLegacy
width colAreaWidth
zoom 1
layout-pattern-child(var)
colWidth = (((var[0] + var[2]) / var[1]) - var[2])
float left
width floor(colWidth)
margin-right var[2]
ul
layout = 400px 5 8px
// 変数をスペース区切りで設定
// foo = 親の横幅 カラム数 カラムの間隔
layout-pattern(layout)
li
layout-pattern-child(layout)
.test
layout = 400px 4 16px
layout-pattern(layout)
.col
layout-pattern-child(layout)
border 1px solid #000
margin-bottom 20px
box-sizing border-box
もしCSSフレームワークを利用していないのであれば、これらのmixinは有効に働きます。
レイアウトのmixinを用意しておくと、全体の幅、カラム数、間隔を指定するだけで、下記のようなレイアウトが簡単に作成できます。
5. positionを利用する
floatは、clearfixなどのテクニックによって、親の高さを出す方法がありますが、positionは親の高さが自動算出する方法がありません。
親の要素に高さを指定しておく必要があります。
.parent {
position: relative;
/*高さがでないことを示すため、あえてボックスよりも短くしている*/
height: 50px;
}
.child1 {
position: absolute;
top: 16px;
left: 8px;
width: 240px;
}
.child2 {
position: absolute;
top: 16px;
right: 8px;
width: 128px;
}
6. positionとmargin
この方法の理屈は、floatとmarginの一定方向を指定する方法と原理は一緒です。
positionがかかっていないボックスの高さが、親の高さとして算出されます。
あまり利用する場面は少ないですが、見出しで飛び出したアイコンを表現する時などに、利用できるかもしれません。
.parent {
position: relative;
}
.child1 {
position: absolute;
top: 16px;
left: 8px;
width: 240px;
}
.p-child2 {
margin-left: 264px;
font-size: 14px;
}
7. display: tableを使った例
display: table; はその名の通り、テーブル要素のように振る舞うことができます。
.parent {
display: table;
width: 100%;
}
.child1,
.child2 {
display: table-cell;
width: 50%;
}
table-cellだけでも、2カラムにすることが可能です。
ただし横幅100%にする場合は、親の要素にdisplay: table; が必要となります。
table-cellだけの例
.child1,
.child2 {
display: table-cell;
width: 50%;
}
8. display: inline-block;を使った例
2カラムというのは、強引かもしれませんが、widthなども利用でき、親の要素にtext-alignを指定すれば、中央寄せなども可能になります。
.parent {
text-align: center;
}
.child1 {
display: inline-block;
width: 240px;
}
.child2 {
display: inline-block;
}
9. CSS3のcolumnプロパティ
今までは、2つのボックスを並べていましたが、このCSS3プロパティは、1つのボックスの中で、複数のカラムを生成することができます。
仕様は勧告候補まで上がっていますが、なかなかベンダープリフィックスが取れず、使いどころの難しいプロパティです。
.parent {
-webkit-column-count: 2;
-moz-column-count: 2;
column-count: 2;
}
10. CSS3のdisplay: flex;
この値は過去に、display: box;, display: flexbox;, display: flex; と名前を変えてきたCSSです。
利用できるブラウザが限定されますが、非常に柔軟なレイアウトが可能になります。
最新のInternet Explorer, Firefox, Google Chromeであれば、ベンダープリフィックスなしのdisplay: flex; が利用可能です。
ただし、Safariやスマートフォンのブラウザのことを考えるのであれば、autoprefixerを利用した方がいいでしょう。
.parent {
display: flex;
justify-content: space-around;
}
.child1,
.child2 {
width: 160px;
}
むすび
これ以外にも、CSS Grid Layout Moduleなどありますが、ブラウザの実装状況が微妙な方法は省きました。
今回10パターンを紹介しましたが、floatに関する部分をマスターすれば、ある程度のレイアウトは組み立てることができます。
複雑そうなレイアウトに見えても、結局は紹介したパターンの繰り返しや、応用がほとんどです。
floatとマイナスマージンで紹介したように、同じことをしつつも面倒な計算が必要となる場合は、Preprocessorなどに任せるのも、ひとつの手です。