Flexboxとの違い

Flexbox は、横か縦の一方を選んでレイアウトできます。
CSS Grid レイアウトは、横と縦の両方でレイアウトでき、よりきめの細かい調整が可能です。

グリッドを作る

display: griddisplay: inline-grid で CSS Grid レイアウトを開始できますが、これだけではグリッドが作れません。

grid-template(grid-template-rows / grid-template-columns)を設定して、グリッドを作ります。
横(columns)と縦(rows)を何分割するかを決めて、調整していきます。
よくありそうなサイトデザインを再現して、以下のように分けてみます。

html

<div class="grid-container">
  <header class="header">header</header>
  <main class="main">main</main>
  <div class="menu">menu</div>
  <footer class="footer">footer</footer>
</div>

css

a.grid-container {
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 100px 1fr;
  gap: 20px 15px;
  min-height: 100vh;
}

.header {
  order: 1;
  grid-column: 1 / 3;
  background-color: #ffff80;
}

.menu {
  order: 2;
  background-color: #ff8080;
}

.main {
  order: 3;
  background-color: #9f9fff;
}

.footer {
  order: 4;
  grid-column: 1 / 3;
  background-color: #9fff9f;
}

便利な記述

見慣れない記述がいくつか見られます。確認してみましょう。

新しい単位 fr

CSS Grid レイアウトでは、fr という新しい単位が使えます。
fr は分割されたスペースのことで、1fr は利用可能なスペース1つ分ということになります。

auto と fr の違い

auto は中のコンテンツに合わせてサイズが変わります。
fr は空いたスペースを埋めてくれます。
組み合わせて使う必要があります。

Flexbox でも使える gap と order

gap と order は、Flexbox でも利用できますが、非常に便利です。

gap(grid-gap / row-gap / column-gap)

アイテムとアイテムの空きを設定できます。
これで最初や最後だけの margin を取り除く、という作業は必要なくなりました。

order

html を入れ替えることなく、レイアウトの表示順を入れ替えることができます。
また grid では、order でなくても下の grid-row と grid-column を設定して入れ替えることもできます。

grid-row / grid-column

grid の子属性のアイテムで、分割した範囲をどのように使うか指定できます。
grid のラインの始まりと終わりを指定するので、分割した数よりも1つ多い数値で設定します。
span 1 とすると、table のようにセル単位の指定もできます。

css

.header {
  grid-column: 1 / 3;
}

.menu {
  grid-row: 2 / 3;
  grid-column: 1 / 2;
}

.main {
  grid-row: 2 / 3;
  grid-column: 2 / 3;
}

.footer {
  grid-column: 1 / 3;
}

決まった形であれば、名前付きが分かりやすい

特に決まりきったレイアウトであれば、grid-template-areas でレイアウトを視覚的に管理できます。
この時、grid-area には名前を設定します。

css

.grid-container {
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 100px 1fr;
  grid-template-areas:
    'header header'
    'menu main'
    'footer footer';
  gap: 20px 15px;
  min-height: 100vh;
}

.header {
  grid-area: header;
  background-color: #ffff80;
}

.menu {
  grid-area: menu;
  background-color: #ff8080;
}

.main {
  grid-area: main;
  background-color: #9f9fff;
}

.footer {
  grid-area: footer;
  background-color: #9fff9f;
}

繰り返すタイルレイアウトも Flexbox より Grid が高機能

タイルレイアウトは、Flexboxでもできますが、CSS Grid レイアウトであれば、きめ細やかな調整が可能です。

html

<div class="card-container">
  <div> 1 </div>
  <div> 2 </div>
  <div> 3 </div>
  <div> 4 </div>
  <div> 5 </div>
  <div> 6 </div>
  <div> 7 </div>
</div>

css

.card-container {
  display: grid;
  grid-auto-rows: 360px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 20px 15px;
}

.card-container > div {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid #000;
}

grid-template の中で使える便利な記述

grid-template-columnsgrid-template-rows で利用できる便利な記述があります。

repeat

繰り返しを簡単に記述できます。
例えば10回記述するとこうなります。

grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;

repeat を使うとすっきりします。

grid-template-columns: repeat(10, 1fr);

auto-fit / auto-fill

repeat の繰り返し数の代わりに利用できるキーワードで、親のスペースが余った部分の埋め方を設定できます。
auto-fill は、親のスペースが余った場合、空のグリッドで埋めます。
auto-fit は、親のスペースが余った場合、アイテムの幅で埋めます。

minmax

アイテムの最小値最大を設定できます。
レスポンシブのときに非常に役立ちます。

grid-auto で規定値を設定

今回のタイルレイアウトだと、アイテムの高さがレスポンシブに影響しないので、 grid-auto-rows で規定値を設定しておくと便利です。

重なりを使ったレイアウト

grid アイテムを重ねて、z-indexを変更して複雑なレイアウトができます。
サンプルが適当ですみません。

html

<div class="container">
  <div> 1 </div>
  <div> 2 </div>
  <div> 3 </div>
  <div> 4 </div>
  <div> 5 </div>
  <div> 6 </div>
  <div> 7 </div>
</div>

css

.container {
  display: grid;
  grid-template-rows: repeat(8, minmax(80px, 1fr));
  grid-template-columns: repeat(6, minmax(120px, 1fr));
  min-height: 100vh;
}

.container > div {
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f1fca2;
}

.container > div:nth-child(1) {
  grid-row: 1 / 3;
  grid-column: 1 / 6;
  background-color: #eee;
}

.container > div:nth-child(2) {
  grid-row: 1 / 5;
  grid-column: 5 / 7;
  background-color: #80ffff;
  z-index: 10;
}

.container > div:nth-child(3) {
  grid-row: 3 / 7;
  grid-column: 1 / 2;
}

.container > div:nth-child(4) {
  grid-row: 2 / 8;
  grid-column: 2 / 3;
  background-color: #fb8383;
  z-index: 20;
}

.container > div:nth-child(5) {
  grid-row: 4 / 7;
  grid-column: 6 / 7;
  background-color: #e787f7;
  z-index: 30;
}

.container > div:nth-child(6) {
  grid-row: 3 / 7;
  grid-column: 3 / 6;
}

.container > div:nth-child(7) {
  grid-row: 7 / 9;
  grid-column: 1 / 7;
  background-color: #90ff80;
}

まとめ

案件で使ってみて、便利だと思いました!