
目次
現在も多いfloatとflex
Webサイトを作成するときに以下のような最大幅520pxで中の余白が20pxの3行 x 3列のレイアウトをCSSで作成するにはfloat: left, display: flex, display: grid のいずれかが使用されることが多い。
しかし、float: leftとdisplay: flexはdisplay: gridに比べてデメリットが多いので、このようなレイアウトで使用するのは好ましくない。
display: gridは使うのが難しいというイメージを持っている人が多いが、シンプルなレイアウトであればfloat: leftやdisplay: flexよりもdisplay: gridのほうが簡単に扱える。
float: leftの場合
float: leftで3行 x 3列のレイアウトを作成する場合は以下のようになる。
<div class="wrap-float">
<div class="box">box1</div>
<div class="box">box2</div>
<div class="box">box3</div>
<div class="box">box4</div>
<div class="box">box5</div>
<div class="box">box6</div>
<div class="box">box7</div>
<div class="box">box8</div>
<div class="box">box9</div>
</div>
.wrap-float {
/* display: flow-root; */
overflow: hidden;
max-width: 520px;
}
.wrap-float > .box {
width: calc(100% / 3 - 40px / 3);
float: left;
padding: 20px;
box-sizing: border-box;
background: skyblue;
}
.wrap-float > .box:not(:nth-child(3n)) {
margin-right: 20px;
}
.wrap-float > .box:not(:nth-last-child(-n+3)) {
margin-bottom: 20px;
}
floatの解除にはoverflow: hidden;を使用しているがIE 11を対象外にするのであれば代わりにdisplay: flow-root;でも有効。
一見すると問題ないように見えるがfloat: leftだとテキストが複数行になったときに同じ行の高さが変わらないという致命的な欠点がある。
foo
また、CSSのコードも21行とflexやgridを使用するよりも多くなってしまう。
さらに.boxの幅はwidth: calc(100% / 3 - 20px * 2 / 3); で計算しているため、余白が20pxから30pxに変わった場合はこの部分も変更しなければならない。
display: flexの場合
display: flexで3行 x 3列のレイアウトを作成する場合は以下のようになる。
<div class="wrap-flex">
<div class="box">box1</div>
<div class="box">box2</div>
<div class="box">box3</div>
<div class="box">box4</div>
<div class="box">box5<br>foo</div>
<div class="box">box6</div>
<div class="box">box7</div>
<div class="box">box8</div>
<div class="box">box9</div>
</div>
.wrap-flex {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
max-width: 520px;
}
.wrap-flex > .box {
width: calc(100% / 3 - 20px * 2 / 3);
padding: 20px;
box-sizing: border-box;
background: skyblue;
}
.wrap-flex > .box:not(:nth-last-child(-n+3)) {
margin-bottom: 20px;
}
foo
CSSのコード量はfloat: leftと比べると少なくなっているが、.boxにmargin-bottomを付けて下の余白を追加しているので、.box:not(:nth-last-child(-n+3)) で最終行以外ののmargin-bottomを追加する処理がこちらも必要になってしまう。
display: gridの場合
display: gridで3行 x 3列のレイアウトを作成する場合は以下のようになる。
<div class="wrap-grid">
<div class="box">box1</div>
<div class="box">box2</div>
<div class="box">box3</div>
<div class="box">box4</div>
<div class="box">box5<br>foo</div>
<div class="box">box6</div>
<div class="box">box7</div>
<div class="box">box8</div>
<div class="box">box9</div>
</div>
.wrap-grid {
display: grid;
gap: 20px;
grid-template-columns: 1fr 1fr 1fr;
max-width: 520px;
}
.wrap-grid > .box {
padding: 20px;
box-sizing: border-box;
background: skyblue;
}
foo
前述のfloat: leftやdisplay: flexに比べてCSSのコードが少なく簡潔になっているのがわかる。
行列の数と余白の値はgap (grid-column-gap, grid-row-gap) と grid-template-rows (grid-template-column) の値を変えるだけなのでレスポンシブWebデザインとの相性も良い。
例えば2列にして行の余白を10px、列の余白を30pxにする場合は以下のようにgapではなくgrid-row-gapとgrid-column-gapにすれば反映できる。
.wrap-grid2 {
display: grid;
grid-row-gap: 10px;
grid-column-gap: 30px;
grid-template-columns: 1fr 1fr;
max-width: 520px;
}
foo
gridにはfrという単位が使える
grid-template-columnsにはfrという単位も使用できる。
frは親要素の幅に合わせたグリッドの幅に自動的に調整することができる単位。
frはfractionの略で「分数」という意味。
例えば3列の中身の幅を1:2:1にしたい場合は「1fr 2fr 1fr」を指定する。
幅520pxでgap: 20px;の場合は(520 - 20 * 2) / 4 = 120なので、1frは120px、2frは240pxとなる。
.wrap-grid-fr {
display: grid;
gap: 20px;
grid-template-columns: 1fr 2fr 1fr;
max-width: 520px;
}
foo
ちなみにgrid初心者だと「1fr 1fr」と「auto auto」は同じと勘違いされることが多い。
autoは1frの代わりにはならず正しく幅が計算されないので注意。
Chromeのデベロッパーツールで確認
Chromeのデベロッパーツールでdisplay: gridの要素部分をElementsタブで確認して「grid」のバッジをクリックすればグリッド表示が切り替わって確認しやすくなる。

デフォルトの1, 2, 3, 4の行番号は今回のケースだと邪魔なのでLayoutのGridから「Hide line labels」で非表示にしてShow track sizesとExtend grid linesを有効にしたほうがdisplay: gridの確認がしやすくなる。


display: gridはIE11でも使えるが…
display: gridはベンダープレフィックスを追加するだけではIE11では使用不可。
.wrap-grid {
display: -ms-grid;
display: grid;
gap: 20px;
-ms-grid-columns: 1fr 20px 1fr 20px 1fr;
grid-template-columns: 1fr 1fr 1fr;
max-width: 520px;
}
ちなみにAutoprefixerで自動付与している。
-ms- を追加するだけでIE11でも使用できると勘違している人は結構多い。
IE11でも3行 x 3列にするにはHTMLとCSSの両方を変えなければならない。
潔くIE11はサポートから除外するのが懸命だ。
ちなみになるべく元のCSSを流用してHTMLを変えてIE11対応の3行3列にする場合は以下のようになる。
<div class="wrap-grid">
<div class="box">box1</div>
<div class="box">box2</div>
<div class="box">box3</div>
</div>
<div class="wrap-grid">
<div class="box">box4</div>
<div class="box">box5<br>foo</div>
<div class="box">box6</div>
</div>
<div class="wrap-grid">
<div class="box">box7</div>
<div class="box">box8</div>
<div class="box">box9</div>
</div>
.wrap-grid3 {
display: -ms-grid;
display: grid;
-ms-grid-columns: 1fr 20px 1fr 20px 1fr;
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;
max-width: 520px;
}
.wrap-grid3:not(:nth-of-type(3)) {
margin-bottom: 20px;
}
.wrap-grid3 > .box {
padding: 20px;
box-sizing: border-box;
background: skyblue;
}
.wrap-grid3 > .box:nth-of-type(1) {
-ms-grid-row: 1;
-ms-grid-column: 1;
}
.wrap-grid3 > .box:nth-of-type(2) {
-ms-grid-row: 1;
-ms-grid-column: 3;
}
.wrap-grid3 > .box:nth-of-type(3) {
-ms-grid-row: 1;
-ms-grid-column: 5;
}
foo