CSS Grid Layout入門
対応ブラウザが出揃った新しいレイアウト仕様

174
199
181

CSSのGrid Layout Module(以下、Grid Layout)とは、ウェブサイトのレイアウトを構築するための新しい仕様です。今まではウェブサイトのレイアウトを実現するために、floatやFlexboxを使っていた方が多いのではないでしょうか。

Grid Layoutを使えば、HTML要素の構造を汚さず、従来の手法に比べてウェブサイトのレイアウトがつくりやすくなります。たとえばfloatだと親要素にdivを増やす必要があったのが、Grid Layoutを使えばそのようなムダなHTML要素を増やさなくて構わなくなります

今回はレイアウトをつくりながら、Grid Layoutの基礎知識について紹介します。余裕のある方は、記事を読みながら実際に手を動かしてレイアウトをつくってみましょう。

この記事で学べること
・Grid Layoutの基本的な使い方
・Grid Layoutの利点
・IE 10以上のブラウザに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で作る場合は

Flexboxを使ってこのレイアウトをつくる場合、横ならびにしたい要素(asidemainnav)をdivなどで囲んでフレックスコンテナーをつくり、横ならびにする要素をフレックスアイテムとして配置します。

わざわざdivを追加する必要があるため、余計な要素が1つ増えますよね。

Grid Layoutで作る場合は

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でつくってみます。

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

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

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

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

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

2つ目はrow(column)-gapでグリッドアイテム間の余白を指定していることです。row(column)-gapは、グリッドアイテムの間にだけ余白ができるようになっています。

floatやFlexboxでこのレイアウトをするには、余白の処理に工夫をする必要があります(例:marginをつけて、レイアウトの端等の不要なmarginをネガティブマージンやE:nth-child(n)で消す) 。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、Edgeの最新バージョンで利用可能、IE10以上では-ms-のベンダープレフィックス付きでサポートされていると記載されています。

ですが、IE10以上〜Edge15のGrid Layoutは2011年時点の仕様である「Grid Layout | W3C Working Draft 7 April 2011」を元に実装されています。Chrome、Firefox、Safari、Edge最新版に実装されている「CSS Grid Layout Module Level 1」とは、対応しているプロパティや仕様に違いが多いため、注意しなければなりません。

IE10〜Edge15の対応方法

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

CSS Grid Layout Module Level 1 IE10以上・Edgeで実装されているGrid Layout 備考
display: grid display: -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

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

IE10/IE11対策にはAutoprefixerがもっとも効果的

Autoprefixer(バージョン8)はベンダープレフィックスを付与するだけでなく、IEの旧仕様をエミュレートする機能が備わっています。grid-template-areasなどIE11で本来は利用できないプロパティでも、互換性のあるコードに変換してくれます。この機能はデフォルトでは無効になっているので、オプションでgrid: trueと指定し有効化します。

▼postcss.config.js

const autoprefixer = require("autoprefixer");

module.exports = {
  plugins: [
    // ベンダープレフィックスを自動付与する
    autoprefixer({ grid: true })
  ]
};

実証サンプルを用意してますので、ご覧ください。

Autoprefixerの使い方は記事「CSSベンダープレフィックスを今この瞬間に辞める為のAutoprefixerの導入」や「webpack 4入門:PostCSS(AutoPrefixerやcssnano)を使う方法」を参照ください。

前述のgapも最新版のAutoprefixerを使えば、IE11で表示可能になります。

モバイルブラウザの対応

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

終わりに

今回はGrid Layoutの基本的なレイアウトの作り方と、プロパティを紹介しました。グリッドレイアウトで実現可能なことは他にもたくさんあります。

弊社池田の記事「CSS Grid Layoutをガッツリ使った所感」では、実際にGrid Layoutでウェブサイトを作ったときの利点や工夫を紹介しています。国内で一番はやくGrid Layoutを投入した事例として、現場で実戦投入したい方の参考になると思います。

続編記事「特徴で使い分けたいCSSレイアウト手法」では、Grid LayoutとfloatとFlexboxとの違いについて紹介します。あわせてご覧くださいませ。

※この記事が公開されたのは2年3ヶ月前ですが、 平成31年3月5日に内容をメンテナンスしています。