CSS: flex-grow の代わりに使う CSS Grid

CSS: flex-grow の代わりに使う CSS Grid

September 16, 2023

私が CSS の Grid を使う場面といえば「The 格子状のレイアウト」のようなデザインを作る時でない限りほとんどありませんでした。複雑なデザインを作ることも少なく、基本的に Flex で事足りるためです。

そんな折に今回、縦1列だけのシンプルなレイアウトであっても Grid が意外と使えるということを知りました。親要素いっぱいに子要素を広げたい場面において、display: flex; flex-grow: 1; を使うことは多いと思いますが、その代わりに display: grid; を用いても同じことが実現できます。

後述しますが、場面によっては display: grid; の方法を用いた方が望ましいこともあるでしょう。

では、以降でその実現方法を見ていきます。

小要素のうち1つを広げたいとき #

以下のページがあるとします。

Default

このページの HTML は次の通りです。

<html>
  <head>
    <style>
      body {
        margin: 0;
        min-height: 100dvh;
        box-sizing: border-box;
        border: 30px solid black;
      }

      header {
        background-color: red;
        height: 300px;
      }

      main {
        background-color: green;
        height: 300px;
      }

      footer {
        background-color: blue;
        height: 300px;
      }
    </style>
  </head>

  <body>
    <header></header>
    <main></main>
    <footer></footer>
  </body>
</html>

ここで <main>(緑色の部分)を空き領域いっぱいに広げて、次のようにしたいです。

Flex

これを実現するための display: flex; および display: grid; を用いたコードは次の通りです。

Flex #

body {
  margin: 0;
  min-height: 100dvh;
  box-sizing: border-box;
  border: 30px solid black;
  display: flex; /* 👈 */
  flex-direction: column; /* 👈 */
}

header {
  background-color: red;
  height: 300px;
}

main {
  background-color: green;
  flex-grow: 1; /* 👈 */
}

footer {
  background-color: blue;
  height: 300px;
}

Grid #

body {
  margin: 0;
  min-height: 100dvh;
  box-sizing: border-box;
  border: 30px solid black;
  display: grid; /* 👈 */
  grid-template-rows: max-content 1fr max-content; /* 👈 */
}

header {
  background-color: red;
  height: 300px;
}

main {
  background-color: green;
}

footer {
  background-color: blue;
  height: 300px;
}

Flex と Grid の違い #

Flex を用いた場合は、親要素と子要素の両方に指定が加わります。対して Grid を用いた場合は、親要素に対してのみ指定が加わります。小要素に書かなければいけない指定はありません。

1つの小要素だけがありそれを広げたいとき #

今度は以下のようなコードがあるとします。<body> は子要素 <main> を1つだけ持っています。

<html>
  <head>
    <style>
      body {
        margin: 0;
        min-height: 100dvh;
        box-sizing: border-box;
        border: 30px solid black;
      }

      main {
        background-color: green;
      }

      p {
        font-size: 80px;
      }
    </style>
  </head>

  <body>
    <main>
      <p>1</p>
      <p>2</p>
      <p>3</p>
      <p>4</p>
      <p>5</p>
      <p>6</p>
      <p>7</p>
      <p>8</p>
      <p>9</p>
      <p>10</p>
      <p>11</p>
      <p>12</p>
    </main>
  </body>
</html>

<main> は複数の子要素を持っていますが、この数は変動します。数字が1〜3までのときもあれば、1〜12までのときもあります。

ここで <main>(緑色の部分)の領域を次のようにしたいです。

<main> が小さいときは <body> の縦幅いっぱいに広げたい <main> が大きいときは <body> を超えて広げたい
Flex Flex

しかし、元のコードのままだと <main> が大きいとき(子要素数が多いとき)は希望の表示になりますが <main> が小さいとき(子要素数が少ないとき)は次のようになってしまいます。

Flex

この対策として次のように height: 100%; を適用してみます。

main {
  background-color: green;
  height: 100%; /* 👈 */
}

そうすると今度は <main> が小さいときは希望の表示になりますが <main> が大きいときは次のようになってしまいます。

Flex

では、希望を実現するためのコードを見てみます。display: flex; および display: grid; を用いたコードは次の通りです。

Flex #

body {
  margin: 0;
  min-height: 100dvh;
  box-sizing: border-box;
  border: 30px solid black;
  display: flex; /* 👈 */
  flex-direction: column; /* 👈 */
}

main {
  background-color: green;
  flex-grow: 1; /* 👈 */
}

p {
  font-size: 80px;
}

Grid #

body {
  margin: 0;
  min-height: 100dvh;
  box-sizing: border-box;
  border: 30px solid black;
  display: grid; /* 👈 */
  grid-template-rows: 1fr; /* 👈 */
}

main {
  background-color: green;
}

p {
  font-size: 80px;
}

Flex と Grid の違い #

両者の違いは先ほどの例と同様です。Flex を用いた場合は、親要素と子要素の両方に指定が加わります。対して Grid を用いた場合は、親要素に対してのみ指定が加わります。

Flex にはない Grid の利点 #

両者の違いで見たように、Grid を用いる場合は親要素に対してのみ指定を当てれば良いのが利点と言えます。

今回は素の HTML で見てきましたが、React を用いていて、children で親コンポーネントに子コンポーネントを渡しているケースを想像してください。Grid の方法で親コンポーネントのほうに display: grid; grid-template-rows: ...; を指定しておけば、そこにどんなコンポーネントを渡しても親が期待するレイアウトにできます。

このように、場面によっては Flex よりも Gird の方が望ましいこともあるでしょう。