段組みのCSS。
グリッドで2段組みレイアウトとまとめ

「グリッド」は、市松模様とか碁盤目みたいな“格子”を表す言葉で、グリッドレイアウトとは、縦線と横線で区切られた格子状のマス目を使って要素を配置するレイアウト手法のこと。CSSでマス目を作って、そのマス目に任意の要素を割り当てていく感覚で、画面をレイアウトしてゆくことができます。フレキシブルボックスレイアウトが要素を柔軟にレイアウトするための仕様だとすれば、グリッドレイアウトは、要素を自由にレイアウトするための仕様ということになります!

グリッドレイアウトの方法

グリッドレイアウトは、displayプロパティの値に用意されたレイアウトモードのひとつ。
なので、使い方は、テーブルやフレキシブルボックスと同じように、displayプロパティでgridという値を指定すれば、その要素でグリッドが利用可能になります。また、gridを指定した要素は「コンテナ」と呼ばれ、その直接の子要素が「アイテム」と呼ばれる点は、フレキシブルボックスと一緒ですね。
ただし、それ以外はフレキシブルボックスと異なるどころか、CSS的にも全く新しいアプローチになるので、他のCSSのことはいったん忘れた方が良いかもしれません¦‹

グリッドレイアウトを行うには、まず、コンテナをグリッドに仕切るところから始まります。
コンテナを、縦横のラインで仕切って、仕切られてできたマス目の横の並びを行トラック、縦の並びを列トラックと呼びます。行トラックと列トラックが交わるひとつひとつのマス目のことを「セル」、セルをいくつか繋げてつくる区画を「エリア」と呼びます。
このエリアに、アイテム要素を割り当てることで、レイアウトを組み立てていく、という流れになります。
フロートや、フレキシブルボックスでは、要素を“流し込む”感覚でレイアウトしていたと思いますけれど、グリッドレイアウトでは、ちゃんとレイアウトすることができるレイアウトモードなんですね:o

CSSのグリッド構造と、各要素の呼び名

gridプロパティ

いろいろ機能があるので、プロパティがすごく大変そうですけれど、「できること」でいうと、フレキシブルボックスよりも少なめです(2017年12月現在)。大きく以下の3つの性質を決めるプロパティに分けられます。

セルのサイズ(横幅と高さ)を決めるプロパティ
grid(grid-template, grid-auto-rows / grid-auto-columns / grid-auto-flow, grid-gap)
grid-template(grid-template-rows / grid-template-columns, grid-template-areas)
セルとセルの隙間を指定するプロパティ
grid-gap(grid-row-gap / grid-column-gap)
アイテム要素を配置するエリアを決めるプロパティ
grid-area(grid-row-start / grid-column-start / grid-row-end / grid-column-end)

そのうち最初の2つは、コンテナとなる要素に指定するプロパティで、最後のはアイテム要素に指定します。
rowが行(上下方向の並び)で、columnが列(左右方向の並び)に対するプロパティを表します。

グリッドレイアウト関連のプロパティ相関図。

グリッドレイアウトの準備

例えば、以下のようなHTMLを用意して、グリッドレイアウトを適用すると要素がどう変化するのか、見ていきたいと思います。div要素の中にむっつのdiv要素が入っていて、コンテナとなる親要素にはcontainer、アイテムとなる子要素にはitemというclass名をつけてます。:)

<div class="container">
	<div class="item">ひとつめのアイテム</div>
	<div class="item">ふたつめのアイテム</div>
	<div class="item">みっつめのアイテム</div>
	<div class="item">よっつめのアイテム</div>
	<div class="item">いつつめのアイテム</div>
	<div class="item">むっつめのアイテム</div>
</div>

.container要素にグリッドレイアウトを適用すると、中のアイテムは以下のようになります。
見たところ特に何も変化がないように見えますけれど、ちゃんとグリッドは作られてます!いまはまだ、なにも仕切りを指定してないので、直接の子要素(アイテム)の数だけ自動的にグリッドが引かれて、縦1列のグリッドが作られている状態です。

.container {
	display: grid;
}

ここから、さらにグリッド関連のプロパティを使って、コンテナにグリッドを作って、レイアウトの基礎を用意します。
CSSで“グリッドを作る”といっても、ピンと来ないですよね…。ちょっと意味がわからないので、さっそく実際にグリッドを作ってゆきます!

グリッドをつくる

グリッドをつくるには、grid-templateプロパティを使います。例えば、ここでは100px / 100px 200px autoという値を指定します。すると下のサンプルのように、要素のレイアウトがガラッと変化しちゃいました!

.container {
	display: grid;
	grid-template: 100px / 100px 200px auto;
}

指定の仕方も何やら複雑ですね…、落ち着いて、ひとつずつ見ていきます。
上の指定では、最初の100px(縦方向の並び)の間隔、スラッシュを挟んで、100px 200px autoが、(横方向の並び)の間隔を表しています。これで、「1行めは高さ100px、2行め以降は指定がないので高さは成り行き」で、「1列めは横幅100px、2列めは200px、3列めはautoなので成り行き幅」というグリッドが作られることになります。

指定する順番は、rowが先

かんたんに言うと、grid-templateプロパティは「行の間隔と、列の間隔を指定して、グリッドを用意するプロパティ」ということになります。

それぞれ、値を半角スペースで区切って列挙することで、列の数、行の数が決まります。つまり、以下のように指定すれば、縦に2行、横に6列のグリッドが作られることになります。

.container {
	display: grid;
	grid-template: 100px 200px / 100px 200px 100px 200px 100px 200px;
}

アイテム要素が6つしかないので、2行めには、アイテム要素は何も配置されません。こんな場合、行に指定しているふたつめの値200pxはどうなるのかというと、レイアウト予定地として、スペースだけ確保された状態になります。
他のCSSプロパティは要素ありきで指定するのに対して、グリッドレイアウトは、要素がなくても、レイアウトのための骨格として余白を作っちゃうんですね:o

配置する要素がなくてもグリッドは用意されちゃう。

ここまでで、コンテナにグリッドを作って、レイアウトの基礎が用意できました。続いて、アイテム要素を、任意の場所に配置してゆきます。
今はアイテムの初期値autoによって、グリッドエリアに自動的に割り当てられた状態になってます。

アイテムを配置する

アイテムを任意のグリッドエリアに割り当てるには、grid-areaプロパティを使います。ここでは、以下のように、よっつめのアイテムに対して2 / 4という風に指定してみました。

.item:nth-child(4) {
	grid-area: 2 / 4;
	background: yellowgreen;
}

これもひとつずつ、詳しく見ていきましょう。
grid-areaプロパティの最初の値2は、グリッドの上から2本めのグリッドラインを指定していることを表します。スラッシュを挟んで、4は、グリッドの左から4本めのグリッドラインを指定していることを表します。
「2行め4列めのグリッドセル」という風に考えることもできるんですけれど、そうじゃなくて、グリッドラインを基準に数えるんですね。なんでこんな考え方をするのかというと、以下のような指定の仕方もできるからなんです。

.item:nth-child(4) {
	grid-area: 2 / 2 / 3 / 7;
	background: yellowgreen;
}

ひとつめの2は上から2本めのグリッドラインで、ふたつめの2は左から2本めのグリッドライン。そして、みっつめの3は上から3本めのグリッドライン。よっつめの7は左から7本めのグリッドラインを表します。わぁーややこやしい!

指定したグリッドラインで囲まれたエリアにアイテム要素を配置する。

つまり、grid-areaプロパティは、「指定したグリッドラインに囲われたエリアにアイテムを配置する」ためのプロパティ、なんですね!グリッドエリアはグリッドラインで囲って指定するってことです。;D
なので、最初の2 / 4という指定も、実は2 / 4 / 3 / 5という風に解釈されてたということです。

ページトップへ戻る

ヘッダーとナビゲーション

さてさてそれでは、そんなグリッドレイアウトを使って、ページレイアウトを行って参りましょう!まずはヘッダーのところを、フレキシブルボックスレイアウトの時のスタイルをもとに、グリッドレイアウトに差し替えてゆきます。
まずはnav要素と、ナビゲーションにdisplay: gridを指定します。nav要素とナビゲーションがコンテナとなって、その直接の子要素がアイテムとなります。
見た目は何にも変わってないけれど、中の要素はしっかりグリッドに備えてる状態になったはずです。

nav要素には、左側にサイトタイトル、右側にはナビゲーションが並ぶので、つまり、行は1行、列は2列です。高さも横幅も成り行きで構わないので、auto / auto autoという風に指定、ちょっと冗長ですね。ナビゲーションは、1行5列なのでauto / auto auto auto auto auto、767px以下の時にはauto / 20% 20% 20% 20% 20%…、冗長が過ぎますね…。
アイテムの配置は自動的に割り当てられたままでも良さそうです。

行はどちらも1行なので、特別にグリッドを用意する必要はなくて、どちらも列方向のみグリッドを仕切ればよいので、grid-template-columnsプロパティで指定し直すことにします。
また、同じ値が繰り返されるような時にはrepeat()関数を使った書き方ができます。括弧の中には、繰り返す回数と、繰り返す値を指定します。例えば、nav要素は2つautoが続くので、repeat(2, auto)という具合。
同じように、ナビゲーションにはrepeat(5, auto)、767px以下の時はrepeat(5, 20%)と指定し直します。

それから、ナビゲーションが左に伸びちゃってバランスが悪いです…。ここは、フレキシブルボックスの時と同じく、justify-contentプロパティで調整することができますspace-betweenという値を指定することで、サイトタイトルとナビゲーションが、両端に寄せて配置されるようになりました:D※その他フレキシブルボックスでおなじみの、align-itemsプロパティalign-selfプロパティitem-contentプロパティorderプロパティも、グリッドレイアウトでも有効です。

メインコンテンツとサイドメニュー

コンテンツエリア#contentsに、グリッドレイアウトを適用して、グリッドを作ります。
コンテンツエリアには、上部にメインビジュアルが鎮座してて、その下にメインコンテンツとサイドメニューがあるレイアウトなので、右図のようにグリッドラインを引くことにしました。

行の高さは成り行きでよいので、列だけ、grid-template-columnsプロパティ75% 25%と指定します。
セルとセルの隙間の指定にはgrid-gapプロパティを使います。けど、ここも列と列の隙間だけ指定すればよいのでgrid-column-gapプロパティで、40pxと指定することにします。

コンテンツエリアに作るグリッド。

これでグリッドが作られました。あとは、アイテム要素である、メインビジュアルと、メインコンテンツとサイドメニューを、グリッドに配置し直してゆきます。
メインビジュアルは、1行めのグリッドセルをまたぐように配置なのでgrid-areaプロパティで、1 / 1 / 2 / 3という風に指定します。メインコンテンツとサイドメニューは2行めのグリッドセルにそれぞれ配置、なのでそれぞれ、2 / 12 / 2ということになります。

サイドメニューが右側にハミ出しちゃってますね…。どうやら40pxの隙間の分、右にズレちゃってるみたい。grid-templateプロパティで指定する値には、隙間は含まないのですね…。メインコンテンツの幅をcalc(75% - 20px)、サイドメニューの幅をcalc(25% - 20px)とすれば大丈夫なはず。
綺麗に収まりました。:)

ページトップへ戻る

バナーと商品一覧と記事一覧

ひとまず、ul要素にグリッドレイアウトを適用して、あとは、flex-basisプロパティで指定してた横幅をそのまま利用すれば、フレキシブルボックスの時と同じレイアウトのグリッドが引けそうです。
あとは、justify-contentプロパティでspace-betweenを適用すれば、できあがり!

もうちょっとグリッドレイアウトらしくレイアウトするなら、隙間は、grid-gapプロパティを使って空けたいです。複数行になるアイテムの上下の隙間も、マージンじゃなくて、grid-gapプロパティで指定した方がスマートですよね。:D

あと、grid-template-columnsプロパティの値が、repeat()関数の中にcalc()関数が入ったりしてごちゃごちゃしてるので、もっとシンプルにしたい…。そこで、グリッドレイアウトで使える「fr」という単位を使って、指定し直すことにします。「fr」は“fraction(比率)”を表す新しい単位。fr単位でサイズを指定した要素には、親要素内の余分なスペースが均等に分配されて、親要素を綺麗に埋めることができるんです。
商品一覧ならば、grid-template-columnsプロパティの値に、repeat(3, 1fr)という風に指定すれば、3列のグリッドセルが等幅で用意されるはずです。

グリッドレイアウトにすることで、CSSを大分スッキリ書くことができましたね;D

お知らせ一覧

フレキシブルボックスレイアウトの時と同じように、日付と内容がよこ並びになるようにグリッドを引けば上手くレイアウトできそうです。grid-template-columnsプロパティで、日付の列は9.8em幅、内容の列は成り行き幅となるようにグリッドを作ります。

フッターのサイトマップ

これまでは「店舗検索」の下に「お知らせ」を配置するために、ネガティブマージンやらパディングやらを駆使してましたが、グリッドレイアウトではその必要はないです!グリッドを用意して、レイアウトすればよいのだから!
下図のようなグリッドを引きたいです。

サイトマップのためのグリッド。

まずは2行5列のグリッドを用意します。行の高さは成り行きで良さそうなので、列だけ、grid-template-columnsプロパティでrepeat(5, 1fr)と指定することにします。隙間はgrid-column-gapプロパティで16pxと指定。
grid-areaプロパティで、「店舗検索」のグループを1行めの3列め、「お知らせ」のグループを2行めの3列めに配置して、あとは成り行きにしちゃいます。

「店舗検索」と「お知らせ」以外は、1行めと2行めをまたいで配置しないとダメでしたね…。
ということで、.group要素には最初に、grid-rowプロパティ1 / 3と指定し、配置するエリアの、行だけを先に決めておくことにします。
並びは順番どおりなのだから、「店舗検索」と「お知らせ」も、行の位置を指定するだけで良さそうですね。grid-areaプロパティをやめて、grid-rowプロパティで指定し直します。

「お知らせ」グループの位置がもうちょっと上だとよいなぁ…。
グリッドの1行めの高さを明示的に指定しちゃいましょう!高さは、他のレイアウトの時に使ったcalc(1.3rem * 1.4 + .9em)にすればよいですね。

ページトップへ戻る

IEでグリッドレイアウト

さて、Internet Explorerは、最新バージョンである「IE11」のサポート終了が2025年10月となっておりますので、まだまだ対応が必要です…。IE11ももちろんグリッドレイアウトには対応してるのですけれど、IE独自のちょっと古いタイプの仕様なので、別途、補足しないといけないんですねー。

※以下、前述までのグリッドレイアウトのことを「グリッドレイアウト」、IE11で使用できるグリッドレイアウトのことを「-ms-グリッドレイアウト」と表記します。

CSSグリッドレイアウトの対応状況は以下のページを参照のこと。
CSS Grid Layout - Can I use...

-ms-gridプロパティ

グリッドレイアウトと、-ms-グリッドレイアウトで定義されている、グリッド関連の主なプロパティは下表の通り。

grid-ms-grid内容
grid-template grid-template-rows -ms-grid-rows 行トラックのサイズを指定する
grid-template-columns -ms-grid-columns 列トラックのサイズを指定する
grid-gap grid-row-gap - 行トラックの隙間の指定する
grid-column-gap 列トラックの隙間の指定する
grid-area grid-row -ms-grid-row アイテムを配置する行トラックを指定する
grid-column -ms-grid-column アイテムを配置する列トラックを指定する
grid-auto-rows - 行トラックのサイズを指定する
grid-auto-columns - 列トラックのサイズを指定する
grid-auto-flow - 自動配置の方法を指定する
justify-self -ms-grid-row-align グリッドエリア内の水平方向の配置を指定する
align-self -ms-grid-column-align グリッドエリア内の垂直方向の配置を指定する
- -ms-grid-row-span アイテムがまたがるグリッドセルの行数を指定する
- -ms-grid-column-span アイテムがまたがるグリッドセルの列数を指定する
グリッドレイアウトと-ms-グリッドレイアウトのプロパティ対応表

グリッドを用意するためのプロパティ-ms-grid-rows-ms-grid-columnsとして用意されてて、アイテムを配置するためのプロパティ-ms-grid-row-ms-grid-columnとして用意されてます。グリッドレイアウトよりもプロパティ名は覚えやすいですね。
けれども、隙間を指定するためのプロパティは用意されてないです…。なので、グリッドを作る際に、隙間もグリッドで用意するということが必要になります(後述)

それから、アイテムの配置の仕方も違うので注意が必要です。
まず-ms-grid-row-ms-grid-columnで、起点となるグリッドセルを指定して、そこから、-ms-grid-row-span-ms-grid-column-spanで、またぐセルの数を指定して、グリッドエリアを作ります。
-ms-グリッドレイアウトには、グリッドラインという概念はないんですねー。

グリッドレイアウトは線、-ms-グリッドレイアウトは面。

それでは、以上を踏まえて、前述までのグリッドレイアウトの指定に、-ms-グリッドレイアウトのための指定を追記してゆきましょう!まずはヘッダーから。
nav要素とナビゲーションに、以下のように追記します。

	display: -ms-grid;
	display: grid;

そして、-ms-グリッドレイアウトでは、-ms-grid-columnsプロパティでグリッドを用意します。
グリッドレイアウトで、repear()関数を使って「repeat(回数, 値)」という風に指定していたところは、-ms-グリッドレイアウトでは、「(値)[回数]」という風に書き換えられます。

@media print, (min-width: 415px) {
	.nav-list {
		⋮
		-ms-grid-columns: (auto)[5];
		grid-template-columns: repeat(5, auto);
@media print, (min-width: 768px) {
	header nav {
		⋮
		-ms-grid-columns: (auto)[2];
		grid-template-columns: repeat(2, auto);
@media screen and (max-width: 767px) {
	.nav-list {
		⋮
		-ms-grid-columns: (20%)[5];
		grid-template-columns: repeat(5, 20%);
IE11での表示(ブラウザで表示する

なんとぉ、サイトタイトルとナビゲーションが一箇所に固まってしまいました。-ms-グリッドレイアウトは、アイテムを自動的に割り付けてくれないんですね…。グリッドレイアウトはアイテムの初期値がauto(空いてるグリッドセルに順番に詰めて配置)だったのに対して、-ms-グリッドレイアウトはアイテムの初期値が1(1行め1列めに配置)ってことなんです。そして整数しか指定できません。
アイテムを列方向のグリッドセルに配置するには、-ms-grid-columnプロパティを使います。とても面倒臭いけれど、下記のように、アイテムをひとつずつ、グリッドセルに配置してゆきます。

@media print, (min-width: 415px) {
	⋮
	.nav-list li:nth-child(2) { -ms-grid-column: 2; }
	.nav-list li:nth-child(3) { -ms-grid-column: 3; }
	.nav-list li:nth-child(4) { -ms-grid-column: 4; }
	.nav-list li:nth-child(5) { -ms-grid-column: 5; }
@media print, (min-width: 768px) {
	⋮
	.nav-list { -ms-grid-column: 2; }
IE11での表示(ブラウザで表示する

無事、グリッドセルにアイテムが順番に配置されました。けれどナビゲーションが左に寄っちゃってますね…。どうやら、nav要素のグリッドのサイズが、アイテムの内容に準拠した幅になってるみたいです。グリッドのサイズをautoじゃなくて、1frに変えてみます。

@media print, (min-width: 768px) {
	header nav {
		⋮
		-ms-grid-columns: (1fr)[2];
		grid-template-columns: repeat(2, auto);
IE11での表示(ブラウザで表示する

それでもまだちょっと左に寄り気味ですね。-ms-grid-column-alignプロパティを使えば、グリッドエリア内のアイテムの横方向の位置揃えを指定できます。ここでは、右側(並ぶ進行方向のお尻側)に寄せるために、endを指定します。

@media print, (min-width: 768px) {
	⋮
	.nav-list {
		-ms-grid-column: 2
		-ms-grid-column-align: end;
IE11での表示(ブラウザで表示する

整いましたX)
続いてコンテンツエリアにグリッドを用意です。
問題はメインコンテンツとサイドメニューの隙間ですが、この隙間も含めて、グリッドを用意しなくちゃいけません。つまり、下記のようにグリッドを引くことになります。

@media print, (min-width: 768px) {
	#contents {
		display: -ms-grid;
		display: grid;
		-ms-grid-columns: calc(75% - 20px) 40px calc(25% - 20px);
		grid-template-columns: calc(75% - 20px) calc(25% - 20px);
		grid-column-gap: 40px;
	}
}

そして、メインビジュアルとメインコンテンツ、サイドメニューを、それぞれグリッドセルに配置します。
メインビジュアルは1行め1列めからの、3つセルをまたぐので-ms-grid-column-spanプロパティ3と指定。メインコンテンツは2行め1列め、サイドメニューは2行め3列め、ですね。
それぞれ、1行め1列めについては、初期値なので特に指定しなくてよいですから、以下のような指定になります。

@media print, (min-width: 768px) {
	⋮
	.visual {
		-ms-grid-column-span: 3;
	}
	main {
		display: block;
		-ms-grid-row: 2;
	}
	aside {
		-ms-grid-row: 2;
		-ms-grid-column: 3;
	}
}

※IE11は、main要素をサポートしていないため、ブロックレベル要素として認識されるように、別途display: blockを指定します。

IE11での表示(ブラウザで表示する

うまくレイアウトできましたーXD
こんな調子で、じゃんじゃか-ms-グリッドレイアウトのための指定を追記してゆき…、できあがり!

IE11での表示

これにて、グリッドレイアウトでページレイアウト完了ー!

ページトップへ戻る

レイアウトのまとめ

いろいろな方法でページレイアウトしてきましたけれども、どれも一長一短あって、適材適所というのが、ちゃんとありますよね。ここまで紹介してきたレイアウトの場合だと、下図のような使い分けが、一番よさげでした。

レイアウト方法の適材適所。

ヘッダーとナビゲーションみたいに単純なよこ並びには、フレキシブルボックスが扱い易いかなと思います。
コンテンツエリアや商品一覧、お知らせ一覧のような、複数行にわたる、文字どおり格子状のレイアウトには、グリッドレイアウトがぴったり。
フッターのサイトマップは、まぐれだと思いますけど、columnsプロパティで一番しっくりレイアウトできちゃいましたねX)
とはいえ、文章中に画像を回り込ませるにはやっぱりfloatプロパティですし、テーブルレイアウトはやはり表組みのためのレイアウトモードでしょうし、インライン・ブロックは、レイアウト用途よりも、文字数幅に準拠させたいタイトルとか、ボタンの中のアイコンとか、もっとピンポイントな用法が相応しいと思います。

選抜レイアウト

なんだかんだ便利なグリッドレイアウトですけれど、他にもまだまだいろんな使い方があって、この記事中のサンプルでは、ぜんぜん本領発揮できていないでしょう。
グリッドレイアウトは、今回レイアウトしたような従来いにしえの段組みレイアウトなどではなくて、ゲーム画面やアプリ画面のような、かっちり決まったレイアウトや、もっと複雑で豊富な機能を画面内に整理整頓しなきゃならないような場面で重宝するレイアウトモードだな、と思いました;)

あとがき

なんでこんなにたくさんの“やり方”があるのかというと、Webは日々進化して、どんどん良くなっているから。その時々での最良のやり方が蓄積されてきた結果なのですね。当然、最新のやり方が、その時のいちばん最良な方法なのだけれど、文章に画像を回り込ませるためにfloatプロパティは残るだろうし、表組みを作るためにテーブルも残るし、要素を並べるためにフレキシブルボックスは使われてゆくと思います。
そんな風に、適材適所のプロパティが増えていった先に、いずれオールマイティに使えるプロパティが登場したりして、また僕らを困惑させるんでしょう。

てなもんで、最後まで読んでいただきありがとうございました!「段組みのCSS。」でした!

Comment & Pingback

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください