CSSにGrid Layout Module(以下、Grid Layout)という仕様があります。今まではグリッドレイアウトを実現するために、floatやFlexboxを使い工夫してレイアウトをつくっていましたが、Grid Layoutを使えば、聖杯レイアウト(Holy Grail Layout)などのグリッドレイアウトがとてもつくりやすくなります。今回はレイアウトをつくりながら、Grid Layoutの基礎知識について紹介します。余裕のある方は、記事を読みながら実際に手を動かしてレイアウトをつくってみましょう。

よくあるレイアウトをつくりながらGrid Layoutの基礎を学ぶ

ヘッダー・メインコンテンツ・左右のサイドバー・フッターがあるレイアウトを例に解説していきます。

<div class="container">
  <header class="header">header</header>
  <main class="main">main</main>
  <aside class="aside">aside</aside>
  <nav class="nav">nav</nav>
  <footer class="footer">footer</footer>
</div>

まずHTMLを書きます。配置する各要素と、それを囲む親要素があります。親要素にはcontainer というクラス名を付けました。

Flexboxを使ってこのレイアウトをつくる場合、横並びにしたい要素(asidemainnav)をdivなどで囲んでフレックスコンテナをつくり、横並びにする要素をフレックスアイテムとして配置する方法が考えられます。Grid Layoutはレイアウトを囲むコンテナの要素(例では.containerにその子要素の配置の仕方を指定していきます。Flexboxと違い、要素を並べる行・列コンテナとなる要素を用意する必要はありません。

Grid Layoutのコンテナとアイテムについて説明しながらCSSでレイアウトをつくっていきます。

グリッドコンテナ

グリッドレイアウトで要素を配置するためにグリッドコンテナをつくります。要素に display: grid を指定すると、その要素はグリッドコンテナになります。(インライン要素として扱うときはdisplay: inline-gridを指定します)

.container {
  display: grid;
}

これだけではまだ要素がただ並んでいるだけです。そこで、グリッドコンテナにグリッドコンテナを分割するための指定をします。

グリッドコンテナを縦・横に分割します。縦方向に分割した各列のサイズはgrid-template-columns 、横方向に分割した各行のサイズはgrid-template-rows で指定します。

列の幅を指定しましょう。今回のレイアウトでは、左のサイドバーの幅が180px、右のサイドバーの幅が160pxです。中央のメインエリアは親要素の幅から左右のサイドバーの幅を引いた可変幅にします。ここで、メインエリアの幅指定にfrという単位を使います。frはグリッドコンテナの中を分割するサイズの指定に使える単位です。全体の幅からfr以外の単位(px%など)で指定したものを引き、残りの幅がfrで指定された列に配分されます。Flexboxのflex-growプロパティと同じようなイメージです。今回は、全体の幅から左右サイドバー(180px、160px)の幅を引いた幅をメインエリアに配分したいので次のように書きます。

.container {
  display: grid;
  /* 1列目から順番に180px、1fr、160pxの幅 */
  grid-template-columns: 180px 1fr 160px;
}

同じように各行の高さも指定していきます。

.container {
  display: grid;
  /* 1列目から順番に180px、1fr、160pxの幅 */
  grid-template-columns: 180px 1fr 160px;
  /* 1行目から順番に60px 1fr 90pxの高さ */
  grid-template-rows: 60px 1fr 90px;
}

このときの列・行のことをグリッドトラックといいます。列・行を分割した線をグリッドラインといいます。グリッドラインは、`border`のように見た目上の線ではありません。

グリッドアイテム

グリッドアイテムを配置していきます。グリッドコンテナ直下の子要素をグリッドアイテムといいます。今回の場合は、ヘッダー・メインコンテンツ・左右のサイドバー・フッターがグリッドアイテムです。

グリッドトラックを分割したグリッドラインは、1本目から順番に1,2,3…と自動的に番号がふられます。grid-column-startgrid-column-endで、グリッドアイテムが列の何本目から何本目のグリッドラインまで配置するか指定します。同じようにgrid-row-startgrid-row-endで行の何本目から何本目のグリッドラインまで配置するか指定します。

.header {
  /* 列の1本目から4本目のグリッドラインまで */
  grid-column-start: 1;
  grid-column-end: 4;
  /* 行の1本目から2本目のグリッドラインまで */
  grid-row-start: 1;
  grid-row-end: 2;
}

このとき、grid-column-endgrid-row-endautoを指定すると、それぞれgrid-column-startgrid-row-startで指定したグリッドラインの次のグリッドラインまでの範囲に配置されます。ヘッダーのgrid-row-endの指定はautoにできます。

.header {
  /* 列の1本目から4本目のグリッドラインまで */
  grid-column-start: 1;
  grid-column-end: 4;
  /* 行の1本目から2本目のグリッドラインまで */
  grid-row-start: 1;
  grid-row-end: auto;
}

同じように他のグリッドアイテムも配置していきます。

.header {
  /* 列の1本目から4本目のグリッドラインまで */
  grid-column-start: 1;
  grid-column-end: 4;
  /* 行の1本目から2本目のグリッドラインまで */
  grid-row-start: 1;
  grid-row-end: auto;
}

.main {
  /* 列の2本目から3本目のグリッドラインまで */
  grid-column-start: 2;
  grid-column-end: auto;
  /* 行の2本目から3本目のグリッドラインまで */
  grid-row-start: 2;
  grid-row-end: auto;
}

.aside {
  /* 列の1本目から2本目のグリッドラインまで */
  grid-column-start: 1;
  grid-column-end: auto;
  /* 行の2本目から3本目のグリッドラインまで */
  grid-row-start: 2;
  grid-row-end: auto;
}

.nav {
  /* 列の3本目から4本目のグリッドラインまで */
  grid-column-start: 3;
  grid-column-end: auto;
  /* 行の2本目から3本目のグリッドラインまで */
  grid-row-start: 2;
  grid-row-end: auto;
}

.footer {
  /* 列の1本目から4本目のグリッドラインまで */
  grid-column-start: 1;
  grid-column-end: 4;
  /* 行の3本目から4本目のグリッドラインまで */
  grid-row-start: 3;
  grid-row-end: auto;
}

grid-column-startgrid-column-endgrid-columngrid-row-startgrid-row-endgrid-rowという略式プロパティで指定できます。このとき、autoは省略できます。今回の .headerはこのように略式プロパティで書き換えることができます。

.header {
  /* 列の1本目から4本目のグリッドラインまで */
  grid-column: 1 / 4;
  /* 行の1本目から2本目のグリッドラインまで */
  grid-row: 1;
}

これでレイアウトは完成です。以下のサンプルでコードと表示を確認してみてください。

タイル状のレイアウトをGrid Layoutで

タイルが並ぶように同じ幅のアイテムが繰り返し配置されるレイアウトをGrid Layoutでつくってみます。

  • 親要素の幅は可変
  • 親要素の幅に収まる、できるだけ多くのアイテムを一行に並べる
  • アイテムの最小幅は100px
  • アイテムの間に10pxの余白をつける
  • その上で親要素の幅があまっている場合はアイテムの幅に均等に分配する

このような条件にします。先に、完成したレイアウトをご覧ください。ウィンドウ幅を変化させて、アイテムの幅や配置をチェックしてみてください。

このようなレイアウトは、floatやFlexboxでもつくることができますがGrid Layoutを使うことで便利になったポイントを紹介します(今回紹介していないプロパティも使っています)。このサンプルでは、Grid Layoutに関するCSSはグリッドコンテナのみに指定しており、少ないプロパティでこのレイアウトをつくることができました。

.container {
  /* グリッドコンテナ */
  display: grid;
  /* 最小100px、最大1frの列を繰り返しつくる */
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  grid-column-gap: 10px;
  grid-row-gap: 10px;
}

レイアウトに関する指定をグリッドコンテナにまとめられる!

まず1つ目に、グリッドコンテナの指定のみでこのレイアウトをつくれるのはとても便利です。floatやFlexboxでレイアウトするとき、親要素にコンテナとなる指定をして、横並びにするアイテムにはアイテムの幅や余白の指定をする必要があったと思います。Grid Layoutでは、グリッドコ
ンテナにグリッドアイテムの配置についての指定ができます。

アイテム間の余白調整が手軽

2つ目はgrid-row(column)-gapでグリッドアイテム間の余白を指定していることです。grid-row(column)-gapは、グリッドアイテムの間にだけ余白ができるようになっています。floatやFlexboxでこのレイアウトをするには、余白の処理に工夫をする必要があります(例:marginをつけて、レイアウトの端等の不要なmarginをネガティブマージンやE:nth-child(n)で消す) 。grid-gapを使えば、そういった調整は必要はありません。

親要素が可変幅でもアイテムのサイズ調整がシンプル

3つ目はgrid-template-columns の値、repeat(auto-fill, minmax(100px, 1fr))です。これは、グリッドトラックのサイズの指定に使えるrepeat()auto-fillを使って親要素におさまるようにアイテムを繰り返し横並びにし、minmaxでアイテムの最小幅・最大幅を指定しています。floatやFlexboxの横並びレイアウトではレスポンシブ対応をするとき、表示の幅によって各列にいくつのアイテムが並ぶように、どんな幅にするかという指定を複数のプロパティでする必要がありました。Grid Layoutのrepeatauto-fillminmaxをうまく使うと、可変幅レイアウトの調整がしやすくなると思います。

ブラウザの実装

Can I use…でGrid Layoutの各ブラウザの対応状況を確認すると、Chrome、Firefox、Safariの最新バージョンでサポート、IE10以上・Edgeでは-ms-のベンダープレフィックス付きでサポートされていると記載されています。ですが、IE10以上・EdgeのGrid Layoutは2011年時点の仕様であるGrid Layout | W3C Working Draft 7 April 2011を元に実装されています。Chrome、Firefox、Safariに実装されているCSS Grid Layout Module Level 1とは、対応しているプロパティや仕様に違いが多いため、注意しなければなりません。

IE10以上・Edgeの対応

IE10以上、EdgeのGrid LayoutについてはMicrosoftによるDeveloper Networkのグリッド レイアウト (Windows)で説明されています。IE10以上・Edgeで対応しているGrid Layout関連プロパティは以下のとおりです。

CSS Grid Layout Module Level 1IE10以上・Edgeで実装されているGrid Layout備考
display: griddisplay: -ms-grid
grid-template-rows(columns)-ms-grid-rows(columns)
grid-row(column)-start-ms-grid-row(column)
grid-row(column)-endなしグリッドアイテムの配置終了位置を指定するプロパティはなし。-ms-grid-row(column)で対応する。
-ms-grid-row(column)-spanグリッドがまたがる行・列の数を指定する。既定値は1。
align-self-ms-grid-column-align
jusitify-self-ms-grid-row-align

IE/EdgeでGrid Layoutを使うのは現実的でないと思っている人も多いかもしれませんが、先ほどの例のように簡単なレイアウトであれば、ベンダープレフィックスを付けることでIE10以上・Edgeに対応できます。

モバイルブラウザの対応

モバイルブラウザは、iOS Safariの10.3以上とChrome for AndroidでGrid Layoutがサポートされています。Android標準ブラウザではサポートされていません。未対応の主要ブラウザがあるうちは、そのウェブサイトの対応ブラウザやデザインを考慮して
部分的にGrid Layoutでレイアウトするなど、工夫をすればGrid Layoutをウェブ制作に役立てることができると思います。

終わりに

今回はGrid Layoutの基本的なレイアウトのつくりかたと、プロパティについて簡単に紹介しました。グリッドレイアウトの関連プロパティやできることは紹介した他にもたくさんあります。例えば、グリッドアイテムを配置するセルに名前をつけたり(grid-template-areas)、グリッドラインに名前をつけることもできます。うまく書くと今回紹介したものよりもっと簡単にグリッドレイアウトをつくれるでしょう。

Grid Gardenというウェブサイトでは、「ニンジン畑に水をあげていく」というコンセプトでゲームGrid Layoutについて学ぶことができます。これを一通りやると、Grid Layoutプロパティの使い方の感覚をつかむ助けになると思いますので、是非やってみてください。

次回、さらに便利にGrid Layoutを使うためにどんなレイアウトがGrid Layoutに向いているのか、floatやFlexboxとの違いについて紹介していきたいと思います。