HTMLの横並びの歴史をたどると、float: left
が主流の時代から、display: flex
が主流の時代となり、そして、新しくdisplay: grid
の時代が到来しようとしています。
大げさに革命という言葉を使いましたが、何が凄いかと言うと、
- 記述用が圧倒的に少なくなる点
- 配置場所の転換が非常に簡単になる点
の2つですね。
IEがなくなるまで使えないと思われがちですが、実はgrid
に関わるほとんどのプロパティはベンダープレフィックスを付与することで利用可能です。
とにかくその利便性から、おそらく今後の主流はdisplay: grid
になってくると思うので、まだあまり理解できていない方はぜひ押さえておきましょう!
display: gridの考え方の基本
grid
は横に○列、縦に○行といった立体的な指定をします。図は横3列 ✕ 縦3行の例ですが、こんな感じでエリアを作ってアイテムを配置していくような形がdisplay:grid;
の基本です。
area1には、このアイテム、area2には、このアイテムといった形で埋めていきます。あるいは、area1とarea2に、このアイテムといった形で複数のエリアを選択して埋めていくことも可能ですし、複数のエリアを選択する際には、area1、area2、area4、area5のアイテムと、area5、area6、area8、area9のようにarea5が被っていても重ねて表示させることも可能だったりします。
上記の図のような表現は以下のコードでおおむね再現可能です。
※ コードの意味は以降で紹介していくので今は深く考えなくても大丈夫です!
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 100px 100px;
}
display: gridの書き方の基本
基本は親要素にdisplay: grid;
を指定するだけです。
※ .grid__item
はエリアを分かりやすくするために色分けしています。
.grid {
display: grid;
}
デベロッパーツールを見ても、girdとして認識されていることが分かります。
ちなみに最近のChromeデベロッパーツールは、グリッドレイアウトのCSSプロパティを認識して操作しやすくしてくれているので、ぜひ活用してみてください!
行と列の枠を指定する
最初の図で見たとおりgrid
の特徴して、枠をあらかじめ用意しておくといったものがあります。○列 ✕ ○行という枠組みをあらかじめ決めておくことが基本となります。
行と列の枠の指定の仕方ですが、
- 列は
grid-template-columns
- 行は
grid-template-rows
で指定します。display: grid;
と同じ要素に指定します。
今回は3列3行ということで指定しようと思います。
.grid {
display: grid;
grid-template-columns: 300px 300px 300px;
grid-template-rows: 150px 150px 150px;
}
grid-template-columns
もgrid-template-rows
も指定の仕方は同様ですが、columns
であれば、左から順番にエリアが確保されていき、rows
であれば上から順番にエリアが確保されていきます。以下の図のような幅と高さが子要素に適応されるような形ですね。
新しい単位「fr」
grid
にはfr
という聞き慣れない単位が使われます。fractionの略のようです。
イメージとしては、table-layout: fixed;
というtable
を等分にするCSSプロパティに近い感覚です。grid
を指定した要素の未指定の幅をfr
の数で割った分の幅が1fr
で確保されます。
例えば、以下のように1fr
で3列作ると3等分になるということですね。
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
では、固定値とfr
が混ざるとどうなるでしょうか?これは、固定値を引いたあとの幅からfr
の数で割った幅が1fr
として認識されます。ここがtable-layout: fixed
と似ているなって思ったりします。
テーブルのCSSに関しては以下の記事でもまとめているのでtable-layout: fixed
が分からない方は「テーブルの列を全て均等にする」を参考にしてください!
例えば、最後の列を600pxで指定すると、600pxを除いた幅から、(fr
が2つなので)2等分して表現してくれます。
.grid {
display: grid;
grid-template-columns: 1fr 1fr 600px;
grid-template-rows: 150px 150px 150px;
background: #eee;
}
繰り返しで指定できる
先ほど3等分するときにgrid-template-columns: 1fr 1fr 1fr;
といった形で1fr
を3回書きましたが、repat()
というCSS関数を使うことで効率的に記載することが可能です。
grid-template-columns: repeat(3, 1fr);
のような書き方をします。
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 150px 150px 150px;
background: #eee;
}
repeat
関数の変数として、繰り返す回数を左側に、繰り返す値を右側に書いてあげればOKです。
配置は自由自在
gird
の特徴は、用意したエリアに対して、子要素を自在に配置変換が可能という点です。スマホでは縦並びだけど、PCの時は、下のコンテンツを左上に配置するみたいな、かつては2重のコードで表現する必要があったことも実にシンプルなコードで実現できてしまいます。
かなり自由に位置を変更してみました。用意したエリアのどこに配置するかは、grid-column
とgrid-row
を子要素に指定することで変更できるようになります。
.grid__item:nth-child(1) {
background: #f8bbd0;
grid-column: 1 / 2;
grid-row: 2 / 3;
}
.grid__item:nth-child(2) {
background: #d1c4e9;
grid-column: 2 / 3;
grid-row: 2 / 3;
}
.grid__item:nth-child(3) {
background: #bbdefb;
grid-column: 2 / 3;
grid-row: 1 / 2;
}
.grid__item:nth-child(4) {
background: #b2ebf2;
grid-column: 3 / 4;
grid-row: 1 / 2;
}
.grid__item:nth-child(5) {
background: #e6ee9c;
grid-column: 1 / 2;
grid-row: 1 / 2;
}
.grid__item:nth-child(6) {
background: #DCEDC8;
grid-column: 3 / 4;
grid-row: 3 / 4;
}
.grid__item:nth-child(7) {
background: #FFF9C4;
grid-column: 2 / 3;
grid-row: 3 / 4;
}
.grid__item:nth-child(8) {
background: #FFCCBC;
grid-column: 1 / 2;
grid-row: 3 / 4;
}
.grid__item:nth-child(9) {
background: #F8BBD0;
grid-column: 3 / 4;
grid-row: 2 / 3;
}
書き方のルールとしては、スタート地点とゴール地点を指定する形です。スラッシュという記号がややこしいですが、これは〇〇から〇〇という範囲を表す役割だと脳内変換してもらえたらと思います。
ちょっと分かりづらいので図にしました。grid
で作成された領域には、こんな感じで番号が振られるようなイメージです。
grid-column: 1 / 2;
とは、1から2の列を指しており、grid-row: 1 / 2;
とは、1から2の行を指しているということです。1から2の列と1から2の行のエリアということで、左上のエリアに配置されるということですね。
ちなみに、この番号が振られた線のことをグリッドラインと呼んだりします。
余白はgapで
grid
の余白がgap
で簡単に設定することができます。使い方としては、列の余白はcolumn-gap
で指定して、行の余白はrow-gap
で指定します。
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 100px 200px;
column-gap: 30px;
row-gap: 30px;
background: #eee;
}
また、列と行のgap
はまとめて書くことができまして、gap
としてgap: 30px 30px;
や列と行が同じ値の場合はgap: 30px;
といった書き方も可能です。
display: flexでの表現をdisplay: gridでやってみる
flexbox
でもやっていたような基本的な表現をgrid
で作ってみようと思います。
カード一覧
これまで紹介しているコードとほぼ同じですが、grid
を使うと余白の定義も簡単ですし、幅を1fr
で等倍にすることで簡単に横並びで等倍のカード一覧を作ることが可能です。
カードの枚数を自動で増減
先ほどの例だとカードは常に3列をキープしたままだと思います。gridでは新しいminmax
という関数と、すでに紹介したrepeat
関数、そして、repeat
関数の中でも繰り返す回数としてauto-fit
を指定することで、かなり柔軟な横並び枚数の調整ができるようになりました!
列の指定に対して、repeat(auto-fit, minmax(300px, 1fr));
のような書き方になります。
※ 300pxは最低限維持したカードの幅。
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 30px;
}
親の幅に対して、入るだけ300pxのカードを入れてくれます。余った余白に関しては、均等に300pxに加えて増やしてくれるような動きですね。入り切らなかった分は次の行に入ります。
要するに、次の動画のように幅に応じて勝手に列数を変えてくれるといった動きになります。
Webサイトのレイアウト
ヘッダー、2カラムのメインコンテンツ(メインとサイドバー)、フッターといったよくあるWebサイトの構成もgrid
で簡単に再現できます。
header
やfooter
をdiv
で囲む必要があるのが、ちょっと嫌な感じはしますが…。body
でやるのもなんか違和感…
子要素の上下中央揃え
grid
もalign-content
とjustify-content
の3行で上下左右の中央揃えが可能です。
幅のない横並び
あらかじめ幅の決まっていない横並びもあると思います。パンくずやユーティリティメニューのような文字のサイズに応じて横並びしたいようなパターンですね。
こちらも対応は可能です。ただし、改行したい場合は、flexboxのほうがいいかもしれません。。
対応方法として具体的にはjustify-content:start;
を指定することで可能となります。もともとjustify-content: stratch;
が適応されているのですが、これが親要素の幅いっぱいにならなくなります。
また、並びをgrid-auto-flow: column;
として、変えてあげます。
横並びでもFlexboxで書いたほうが良さそうなパーツ
grid
が主流になってもFlexboxで書きそうなパーツです。おそらく、よしなに改行してほしいみたいな並びはFlexboxになるのかと思います。
例えば、以下のような横並びのユーティリティメニューなど。
1次元レイアウトがFlexbox、2次元レイアウトがGridという説明をされていることが多いように思います。単純な1次元の横並びのレイアウトの場合は、Flexboxを検討するといいのかもしれません。
位置関係のプロパティの整理
この記事ではあまり登場していませんが、、、位置に関するプロパティがたくさんあるので整理しておきましょう(使う必要が出てきたときに、この章を見返してもらえらと思います)
親要素内のでの位置の調整
display:grid;
のエリアに対して、各子アイテムをどういった位置関係で並べるかを決めるためのプロパティとなります。他の子アイテムを意識しながら決めていくのがポイントですね。
justify-content
・・・横の位置をどう揃えるかalign-content
・・・縦の位置をどう揃えるか
display:grid;
は何もしなければ親要素のエリアいっぱいを使ってスペースを埋めるような動きをします。上記のプロパティで位置を指定することで、自動でスペースを使う機能を解除して、列や行の配置関係を決めることが可能です。
子アイテムの位置
子アイテムが用意されたエリアの中で、どの位置に配置するかを決めるものです。こちらは、他の子アイテムのことは意識せずに自分のエリアの中だけで考えます。
justify-items
・・・左右の位置関係align-items
・・・上下の位置関係
display: gridをIE対応するために
gridはベンダープレフィックス(と読んでいいのか分からないほど書き方が変わりますが…)を使えば、IE対応できます。基本的には覚える必要はなく、機械に任せて変換させてしまいましょう。
ベンダープレフィックスの付与
grid
はIEに対応していなさそうな雰囲気をめちゃくちゃ出していますが、実はほとんどのプロパティはベンダープレフィックスやIE用の書き方をしてあげれば問題なく機能します。
autoprefixerを使っている方はGulpでpostcss([autoprefixer({ grid: true })])
といった形で
grid: true
を付与してあげれば機能するようなります。
const gulp = require("gulp");
const sass = require("gulp-sass");
const postcss = require("gulp-postcss");
const autoprefixer = require("autoprefixer");
gulp.task("sass", function() {
return gulp
.src("./src/**/*.scss")
.pipe(sass({ outputStyle: "expanded" }))
.pipe(postcss([autoprefixer({ grid: true })]))
.pipe(gulp.dest("./public"));
});
例えば、これまで紹介してきたようなgridの書き方を、Autoprefixerを通してIE用のプロパティを加えると以下のような変化になります。
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 100px 200px;
}
.grid__item:nth-child(1) {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
↓
.grid {
display: -ms-grid;
display: grid;
-ms-grid-columns: (1fr)[3];
grid-template-columns: repeat(3, 1fr);
-ms-grid-rows: 100px 200px;
grid-template-rows: 100px 200px;
}
.grid__item:nth-child(1) {
-ms-grid-column: 1;
-ms-grid-column-span: 1;
grid-column: 1 / 2;
-ms-grid-row: 2;
-ms-grid-row-span: 1;
grid-row: 2 / 3;
}
プロパティ名から値からほとんど分かっていると思いますが、覚える必要はないと思います。Autoprefixerに身を任せて対応しましょう。
gapが使えない
悲しいことにIEでgap
が使えません。そしてベンダープレフィックスもありません。また、ポリフィル的なものもなさそうです(あれば教えてください…)
ということで、IEではgap
で余白が制御できない前提でレイアウトを考える必要があります。
- 各エリアに
padding
で余白を設定する - 各エリアに
margin
で余白を設定する - IE以外は
gap
を設定しておいて、IEの場合だけmargin
やpadding
をつける指定をする
みたいな選択肢になるかと思います。
rowを明示的に指定する
カードの作り方のところで、以下のように指定することで3枚以上になっても自動で列が増えてカードを作れたかと思いますが、IEでは行が勝手に増えることはありません。
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
IEでgrid
を使う際は、列もちゃんと指定する必要があります。WordPressの投稿一覧のように何枚カードが入るか分からないようなグリッドレイアウトをIE対応を前提に作る場合は、flexbox
の方が向いていますね…。
おわり
grid
に関する初歩的な概念と使い方でした!grid
を使うことで
- 記述用が圧倒的に少なくなる点
- 配置場所の転換が非常に簡単になる点
の大きなメリットを受けることができます。CSSの各プロパティには状況に応じた使い方があって、全てが全てgrid
になるわけではないと思いますが、便利なプロパティであることは間違いないので、まだ慣れていない人はぜひ少しずつ使ってみてください!