CSSグリッドレイアウトの基本と使い方をマスターする

どうも、SeikouUdokuのケイトです。

今回は、CSS Grid Layout(グリッドレイアウト)について自分なりにまとめてみましたので、ご紹介したいと思います。

はじめに

グリッドレイアウトとは、二次元グリッドシステムをcssで簡単に表現することができます。

グリッドとは、水平線と垂直線の集合が交差したものです。一方は列を定義し、もう一方は行を定義します。要素は、グリッド上の行と列の中に配置することができます。

横並びのレイアウトといえば、floatflexを使っていると思います。
行または列のみによって制御する時はこれらは便利ですが、行および列により制御するレイアウトを作る時は、不便です。
できないことはないのですが、コード量も増えるし、やりにくいなぁと思っている人が多いのではないでしょうか?

グリッドレイアウトでは、エクセルのように複数の行と列の二次元で考えるためそれらの煩わしさを解決することができます。

グリットレイアウトの対応ブラウザも増えており、今後利用するのに便利なプロパティになりそうです。
CSS Grid Layout (level 1)

グリッドレイアウトの作成

まず、本サイトのブログ一覧のレイアウトをみてみましょう。グリッドレイアウトを使えば、こういったレイアウトが簡単に組むことができます。

gridlayout1

上図ようなブログ一覧のデザインは、グリッドレイアウトでは下図のようになります。

gridlayout2

グリッドレイアウトの作成方法としては大きく以下の手順です。

  1. グリッドコンテナーの作成
  2. グリッドトラックの作成
  3. グリッド線やグリッドエリアを利用してグリッドアイテムを配置

それでは、グリッドレイアウトで使う各用語の説明とプロパティの指定方法を説明します。

グリッドコンテナー

グリッドレイアウトにするためには、要素に対してdisplay: grid;または、display: inline-grid;を指定します。指定した要素をグリッドコンテナーと呼びます。

<div class="wrapper" style="display:grid;"> <!-- グリッドコンテナー -->
  <div class="item">1</div> <!-- グリッドアイテム -->
  <div class="item">2</div> <!-- グリッドアイテム -->
  <div class="item">3</div> <!-- グリッドアイテム -->
  <div class="item">4</div> <!-- グリッドアイテム -->
  <div class="item">5</div> <!-- グリッドアイテム -->
  <div class="item">6</div> <!-- グリッドアイテム -->
</div>

グリッドアイテム

グリッドコンテナー直接の子要素グリッドアイテムと呼びます。

グリッドトラック

グリッド上に行と列を定義します。グリッドトラックは、グリッド上の任意の2本の線の間にあるスペースを指します。
何行で何列なのか、またそのサイズを指定することができます。

列の指定:grid-template-columns
行の指定:grid-template-rows

(例)一つの大きさが200pxの3列の記述

<div class="wrapper">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: 200px 200px 200px; 
}

gridlayout3

fr単位

frとはfraction(分数)の略称です。グリッドトラック幅を比率で表すことができます。frの前に数字を指定して使います。

(例)3等分の列の記述

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr; 
}

gridlayout4

絶対サイズとfr単位を混合することも可能です。

(例)3列で1列目が150px、2列目と3列目の比率が2:1の記述

.wrapper {
  display: grid;
  grid-template-columns: 150px 2fr 1fr; 
}

gridlayout5

repeat()記法

repeat()記法を使うことで、トラックのすべてまたは一部を繰り返し表記することができます。

先ほどの「3等分の列の記述」を例にあげると、以下のように記述可能です。

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

暗黙的と明示的なグリッド

ここまで、列を定義するgrid-template-columnsのみを使ってきました。しかし、グリッドは自動で行も作っていることが図からわかります。この時にできる行を暗黙的なグリッドと呼びます。暗黙的なグリッドはコンテンツに合わせて自動でサイズが調整されます。

gridlayout6

その暗黙的なグリッドに対して、サイズを定義することができます。

列のサイズ:grid-auto-columns
行のサイズ:grid-auto-rows

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 200px);
  grid-auto-rows: 100px;
}

gridlayout7

minmax()関数

minmax()関数を使うことによって、グリッドに対して最小サイズや最大サイズを指定することができます。

例えば、「行の高さを100pxより小さくはしたくない。だけど100pxを超えた場合は、行の高さを自動で合わせてほしい」みたいな時があると思います。そんな時、以下のように記述することで解決できます。

minmax(最小値, 最大値)で記述します。

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 200px);
  grid-auto-rows: minmax(100px, auto);
}


グリッドアイテムを配置するためのパターン

ここまで、グリッドトラックを定義して、グリッドレイアウトを作成してきました。
グリッドレイアウトには、その他にグリッド線、グリッドセル、グリッドエリアという概念があります。
これらを定義することでグリッドアイテムの配置を柔軟に行うことができます。

例として、以下の3×3のグリッドレイアウトを用いてグリッドアイテムを配置する方法を2パターン説明します。

gridlayout8

■ パターン1:グリッド線からグリッドアイテムを配置する

グリッドレイアウトにおいて、行や列を定義したときに番号のついた線が与えられます。
この線をグリッド線と呼びます。
また、グリッド上の最も小さな単位をグリッドセルと呼びます。

gridlayout9

グリッド線は、列が左から右に1, 2, 3, 4、行が上から下に1, 2, 3, 4と番号が与えられます。またそれぞれ-(マイナス)での番号も同時に与えれます。
1, 2, 3, 4 → -4, -3, -2, -1

このグリッド線の範囲を定義するプロパティが以下です。

列のグリッド線:grid-column
行のグリッド線:grid-row

始線の番号 / 終線の番号で記述します。

ここで、例の「item-a」のグリッド線について考えてみましょう。

gridlayout10

列が1から4の範囲で、行が1から2の範囲であることがわかります。これを記述すると以下になります。

<div class="wrapper">
  <div class="item-a">item-a</div>
  <div class="item-b">item-b</div>
  <div class="item-c">item-c</div>
  <div class="item-d">item-d</div>
  <div class="item-e">item-e</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 100px); 
}

.item-a {
  grid-column: 1 / 4;
  grid-row: 1 / 2;
}

始線の番号と終線番号には別の記述方法があります。

spanを用いて線の範囲を指定する方法です。

また、隣り合う線の場合は終線の番号を省略することができます。

このことを踏まえて、「item-a」は以下のように記述することもできます。

.item-a {
  grid-column: 1 / span 3;
  grid-row: 1;
}

grid-column: 1 / span 3;とは、列の1つ目の線から始まり、3つ先の線で終わるという意味になります。つまり列の1から4までの線の範囲を表します。

grid-row: 1;とは、行の1つ目の線から始まり、2つ目の線で終わるという意味になります。つまり行の1から2までの線の範囲を表します。

さて同様に、item-b、item-c、item-d、item-eも考えると、このグリッドレイアウトは以下のように記述することで表すことができます。

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

.item-a {
  grid-column: 1 / span 3;
  grid-row: 1;
}

.item-b {
  grid-column: 1;
  grid-row: 2 / span 2;
}

.item-c {
  grid-column: 2 / span 2;
  grid-row: 2;
}

.item-d {
  grid-column: 2;
  grid-row: 3;
}

.item-e {
  grid-column: 3;
  grid-row: 3;
}

■ パターン2:グリッドエリアを指定してグリッドアイテムを配置する

行と列の単一や複数のグリッドセルからグリッドエリアを作ることができます。

グリッドセルには任意のエリア名をつけることができます。これを利用してグリッドエリアを作成し、グリッドアイテムを配置することができます。

ここで、例の3×3のグリッドレイアウトにエリア名をつけてみましょう。

gridlayout11

次にグリッドエリアを定義するプロパティにエリア名を記述していきます。

グリッドエリアの作成:grid-template-areas
グリッドエリアの指定:grid-area

grid-template-areasグリッドコンテナーに記述し、grid-areaグリッドアイテムで記述します。

<div class="wrapper">
  <div class="item-a">item-a</div>
  <div class="item-b">item-b</div>
  <div class="item-c">item-c</div>
  <div class="item-d">item-d</div>
  <div class="item-e">item-e</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 100px);
  grid-template-areas: "area-a area-a area-a"
                       "area-b area-c area-c"
                       "area-b area-d area-e";
}

.item-a {
  grid-area: area-a;
}

.item-b {
  grid-area: area-b;
}

.item-c {
  grid-area: area-c;
}

.item-d {
  grid-area: area-d;
}

.item-e {
  grid-area: area-e;
}

grid-template-areasプロパティは、行ごとエリア名を列の数だけ記述してダブルクォーテーションで囲ってください
エリアが複数セルにまたがっている時は、同じ名前のエリア名を記述します。

最後に、各グリッドアイテムgrid-areaプロパティでエリア名を指定することで、グリッドアイテムを配置することができます。

セルの間隔

グリッドアイテム同士の間隔を指定することができます。

縦方向の間隔:column-gap
横方向の間隔:row-gap
縦と横方向の間隔をまとめて指定:gap

<div class="wrapper">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 30px;
  row-gap: 20px;  
}

縦と横方向の間隔をまとめて指定する場合は、二つの値を半角スペース区切りで指定します。一つ目の値がrow-gap、二つ目の値がcolumn-gapです。

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px 30px;  
}

gridlayout12

入れ子状のグリッド

グリッドアイテムは、グリッドコンテナーになることもできます。
入れ子状のグリッドは、親グリッドと関係性はなく、プロパティを継承することはありません。

gridlayout13

<div class="wrapper">
  <div class="item-a">
    <div>1</div> <!-- 入れ子状のグリッド -->
    <div>2</div> <!-- 入れ子状のグリッド -->
    <div>3</div> <!-- 入れ子状のグリッド -->
  </div>
  <div class="item-b">item-b</div>
  <div class="item-c">item-c</div>
  <div class="item-d">item-d</div>
  <div class="item-e">item-e</div>
</div>
.item-a {
  grid-column: 1 / span 3;
  grid-row: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

このように、グリッドアイテムである「item-a」をグリッドコンテナーにすることで、入れ子状のグリッドを作成することができます。

グリッドアイテムの重なり

グリッドアイテムは、同じセルを占有することができます。
例として、以下のように「item-a」と「item-b」が一部のセルを占有しているグリッドレイアウトがあるとします。

gridlayout14

<div class="wrapper">
  <div class="item-a">item-a</div>
  <div class="item-b">item-b</div>
  <div class="item-c">item-c</div>
  <div class="item-d">item-d</div>
  <div class="item-e">item-e</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 50px;  
}

.item-a {
  grid-column: 1 / span 3;
  grid-row: 1 / span 2;
}

.item-b {
  grid-column: 1;
  grid-row: 2 / span 4;
}

グリッドアイテムの重なりは、ソースコードに書かれた順に後のものが上になります。
この重なりの順番をz-indexプロパティで制御することができます。「item-a」を上にしてみます。

.item-a {
  grid-column: 1 / span 3;
  grid-row: 1 / span 2;
  z-index: 2;
}

.item-b {
  grid-column: 1;
  grid-row: 2 / span 4;
  z-index: 1;
}

gridlayout15

まとめ

いかがでしたでしょうか?
これで、グリッドレイアウトの概念と使い方をある程度理解できたのではないでしょうか?
グリッドレイアウトを利用することで、様々なレイアウトが組みやすくなるでしょう。

ただ、floatflexを全く使わなくなるといったことではなく、使い分けが必要になりそうです。
グリッドレイアウトと他のレイアウト方法との関係は以下を参照にしてみてください。
グリッドレイアウトと他のレイアウト方法との関係 – CSS: カスケーディングスタイルシート | MDN

あなたへのオススメ記事