sample1(固定幅)
sample2(可変幅)
sample3(簡易レスポンシブ)
固定幅レイアウトにもリキッドレイアウトにも応用できるグリッドCSSを作ってみた。特徴は、
- 個々のカラム幅をパーセントで指定するので、固定幅レイアウトにもリキッドレイアウトにも応用できる。
- カラム間の余白(ガター/溝)はピクセル単位で指定できる。
- 1行ごとにカラムの高さを揃えることができる。
- ソースの入れ子記述を最小限にした。
- IE8以降に対応。
とりあえず
1行の横並びカラムは下のような構造になる。後で、個々のカラムの内側や1行全体の外側に余白を設けるためいくつか子要素や親要素などを作り多重の入れ子になるが、最終的には下の記述のみですませたい。
<div class="grid">
<div class="col-2-3">2/3幅</div>
<div class="col-1-3">1/3幅</div>
</div>
カラム幅は単純にパーセントで指定し、1行のカラム幅の合計が100%になるようする。
.col-1-3 {width: 33.33%;}
.col-2-3 {width: 66.66%;}
.col-1-2 {width: 50%;}
.col-1-4 {width: 25%;}
floatで横並びさせる。
[class*='col-'] {
float: left;
padding-left: 20px;/*ガター幅*/
}
1行の横並びカラムの囲い。1カラム分のpaddingだけはみ出るので、それだけ左マージンをネガティブで広く取る。
.grid{
margin:0 0 20px -20px;
/*左マージンを1カラムpadding分広く取る。次の行との隙間を下マージンで取る。*/
overflow:hidden;/*フロート解除*/
background-color:transparent;/*ネガティブマージンだと要素が重なるので透明に*/
}
このままではカラムの実際幅がカラム指定幅 + ガター幅になって行をはみ出してしまう。そこでカラムの実際幅 + ガター幅がカラム指定幅になるようにする。そのためにカラムを box-sizing:border-box; とする。
[class*='col-']{
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
次にカラムの内側一杯に子要素を作る(<div class="inner">)。カラムのバックグラウンドカラーやボーダー、パディングは実際はこの子要素に対して行う。
<div class="grid">
<div class="col-2-3"><div class="inner">2/3幅</div></div>
<div class="col-1-3"><div class="inner">1/3幅</div></div>
</div>
.inner{
margin:0;
height:100%;
background:#ccc;/*背景色*/
color:#000;/*文字色*/
padding:.5em;/*カラムの内側の余白/
}
外側にもガターを作る
上のやり方では grid の幅いっぱいにカラムが並ぶ。そこで必要に応じて、外側にもガターを作ることにする(<div class=grid-outer> </div>)。そのためには、grid を囲う親要素を作り適当なpaddingを指定すればよい。外側にガターを作りたいときもあるしそうでないときもあるので、指定することにする。つまり<div class="grid out-gutter">にだけ外側ガターを作る。
<div class="grid-outer">
<div class="grid out-gutter">
<div class="col-2-3"><div class="inner">2/3幅</div></div>
<div class="col-1-3"><div class="inner">1/3幅</div></div>
</div>
</div>
.grid-outer{
margin:0 0 20px 0;
padding:20px;
background:#888;
}
.grid-outer > .grid{
margin-bottom:0;/*次の行との余白はgrid-outerクラスのブロックが受け持つのでgridクラスは下のマージンが不要*/
}
カラムの高さを揃える
好みの問題かもしれないが行ごとにカラムの高さを揃えてもよい。そのためには jquery.matchHeight.js というプラグインを使うのが簡単だ。jquery.matchHeight.js はデフォルトで行単位でブロックの高さを揃えてくれる。
使い方は下のスクリプトを記述すればよい。
<script type = "text/javascript" src = "jquery-1.10.2.min.js"></script>
<script type = "text/javascript" src = "jquery.matchHeight.js"></script>
<script type = "text/javascript">
$(document).ready(function() {
$("div[class*='col-']>.inner").matchHeight();/*div[class*='col-']だとborder-bottomが消える?*/
});
</script>
ソースをシンプルにする
innerクラスやgrid-outerクラスのブロックを作ったことで、ソースが多重の入れ子になってしまった。読みやすさとマークアップ時の書き間違い防止ため、一番最初に示した単純なコードだけですませたい。
そのためにinnerクラスとgrid-outerクラスをjQueryを使って自動的に挿入するようにする。
外側のガター追加は<div class="grid out-gutter">に対して行う。
単純になったHTMLソースを再掲。
<div class="grid">
<div class="col-2-3">2/3幅</div>
<div class="col-1-3">1/3幅<br>高さが揃う</div>
</div>
<div class="grid out-gutter">
<div class="col-2-3">2/3幅</div>
<div class="col-1-3">1/3幅<br>高さが揃う</div>
</div>
javascriptの順序があるようなので matchHeight の記述も再掲する。
<script type = "text/javascript" src = "jquery-1.10.2.min.js"></script>
<script type = "text/javascript" src = "jquery.matchHeight.js"></script>
<script type = "text/javascript">
$(document).ready(function() {
$("div[class*='col-']").wrapInner("<div class='inner'></div>");
$(".out-gutter").wrap("<div class='grid-outer'></div>");
$("div[class*='col-']>.inner").matchHeight();
});
</script>
レスポンシブへの足がかり
479px以下のモバイルを想定して、簡単にレスポンシブ・レイアウトにも対応させてみた。ここでは479px以下はすべてのカラムの指定幅を100%にし、1行1カラムで表示することにした。加えるCSSは、
@media only screen and (max-width: 479px) {
body{
margin:0 10px;
}
[class*='col-']{
width:100%;
clear:left;
margin-bottom:20px;
}
.grid >div[class*='col-']:last-child {
margin-bottom: 0;
}
}
:last-child 疑似要素(IE8非対応)を使ったということもあって、IE8も対応できるようにIE9.js とか respond.js とかを使うことも考えたが、どうせモバイルでIE8使わないだろうということでで止めた(実は少し試してみたのだが、どこが悪かったのかうまくいかなかった orz)。
参照サイト:
http://coliss.com/articles/build-websites/operation/css/css-tutorial-flexible-grid-by-css-tricks.html
https://css-tricks.com/dont-overthink-it-grids/
jquery.matchHeight.js
http://brm.io/jquery-match-height/
参照サイトのソースはほぼ同じだが、グリッドの外側にgutterなしの場合実は正しく表示されない。端のカラムだけ幅が広くなる。それと、IE8以上と書いてあるが実はうまく表示されない。CSSのlast-of-type属性がサポートされていないためであろう。
その他、ボックスの高さが揃わない、入れ子divがうっとうしいといったことがあったので作ってみた。