HTML / CSSのレイアウト革命!display:gridの使い方を理解してスマートにコーディングしよう!

HTMLの横並びの歴史をたどると、float: leftが主流の時代から、display: flexが主流の時代となり、そして、新しくdisplay: gridの時代が到来しようとしています。

大げさに革命という言葉を使いましたが、何が凄いかと言うと、

  • 記述用が圧倒的に少なくなる点
  • 配置場所の転換が非常に簡単になる点

の2つですね。

IEがなくなるまで使えないと思われがちですが、実はgridに関わるほとんどのプロパティはベンダープレフィックスを付与することで利用可能です。

とにかくその利便性から、おそらく今後の主流はdisplay: gridになってくると思うので、まだあまり理解できていない方はぜひ押さえておきましょう!

MDN Web Docs
グリッドレイアウトの基本概念 - CSS: カスケーディングスタイルシート | MDN CSS グリッドレイアウトは、二次元グリッドシステムを CSS にもたらします。グリッドは、主要なページ領域や小さなユーザーインターフェイス要素のレイアウトに利用できま...
目次

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プロパティを認識して操作しやすくしてくれているので、ぜひ活用してみてください!

コリス
デベロッパーツールの新機能が便利!CSS Gridの実装と検証が簡単になるCSS Grid editorとオーバーレイ 先日リリースされたChrome 92のデベロッパーツールに、CSS Gridの実装に役立つ新機能が2つ加わりました! 1つ目はCSS Grid editorでデバッキングツール、2つ目はCSS Gri

行と列の枠を指定する

最初の図で見たとおり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-columnsgrid-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が分からない方は「テーブルの列を全て均等にする」を参考にしてください!

あわせて読みたい
CSSでテーブルを作る上で実践的に覚えておきたいこと CSSのテーブルは癖が強いというか、どういう風な仕組みで動いているか分かりにくいCSSにプロパティだと思います。 よくあるのは、レスポンシブ時にはみ出る、、、という...

例えば、最後の列を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-columngrid-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で簡単に再現できます。

headerfooterdivで囲む必要があるのが、ちょっと嫌な感じはしますが…。bodyでやるのもなんか違和感…

子要素の上下中央揃え

gridalign-contentjustify-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で余白が制御できない前提でレイアウトを考える必要があります。

  1. 各エリアにpaddingで余白を設定する
  2. 各エリアにmarginで余白を設定する
  3. IE以外はgapを設定しておいて、IEの場合だけmarginpaddingをつける指定をする

みたいな選択肢になるかと思います。

rowを明示的に指定する

カードの作り方のところで、以下のように指定することで3枚以上になっても自動で列が増えてカードを作れたかと思いますが、IEでは行が勝手に増えることはありません。

.grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
}

IEでgridを使う際は、列もちゃんと指定する必要があります。WordPressの投稿一覧のように何枚カードが入るか分からないようなグリッドレイアウトをIE対応を前提に作る場合は、flexboxの方が向いていますね…。

おわり

gridに関する初歩的な概念と使い方でした!gridを使うことで

  • 記述用が圧倒的に少なくなる点
  • 配置場所の転換が非常に簡単になる点

の大きなメリットを受けることができます。CSSの各プロパティには状況に応じた使い方があって、全てが全てgridになるわけではないと思いますが、便利なプロパティであることは間違いないので、まだ慣れていない人はぜひ少しずつ使ってみてください!

この記事が気に入ったら
いいね または フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

WordPressが得意なWeb屋。HPcode代表。

300件以上のWordPressカスタマイズを対応してきました。SE → 農家 → アフィリエイター → Web屋。生まれは三重県。

目次