CSSレイアウト対決！FlexBoxとGridでカードを実装してみた

# はじめに
CSSでレイアウトを組むとき、「**FlexBoxこそが神！**」と言われるほど**FlexBox**を愛用していました。しかし、カード形式の実装では**Flexbox**だと手間がかかり、思ったようにレイアウトできないことがありました。

ある時、```ChatGPT```に「カードを実装してください」と依頼したところ、「**Grid**」で実装するコードが返ってきました。そのコードを見て、簡単に実装できることに驚き、「**Grid最高！**」と感動しました。

今回はその内容についてまとめます。

# Flexboxでカード実装

まずは「**Flexbox**」でカードを実装します。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="eYwYWmr" data-pen-title="Untitled" data-user="rei-dev99" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/rei-dev99/pen/eYwYWmr">
  Untitled</a> by rei-dev99 (<a href="https://codepen.io/rei-dev99">@rei-dev99</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

### 説明

#### ポイント1
- 親要素で**Flexbox**対応、折り返し、列行間を指定

```:css
.flex-container {
  display: flex;
  flex-wrap: wrap;
  gap: 30px;
}
```

#### ポイント2

- 子要素の伸び率と縮み率を一定にし、幅を```50%```として、```30px分```をマイナス

```:css
.card {
  flex: 1 1 calc(50% - 30px);
}
```

これは「**flex-grow**」「**flex-shrink**」「**flex-basis**」をまとめて記述したものです。
子要素の伸び率を一定(```flex-grow```と```flex-shrink```)にして、幅を```50%```(```flex-basis```)に設定し、```gap```で指定した```30px```分をマイナスにしてます。

#### おまけ

- 行列間の指定

```
gap: 30px;
```
この```gap```のおかげで次の**nth-child**を使ったマージン指定を省略できています。
```
.card:not(:nth-child(2n + 1)) {
  margin-left: 30px;
}
.card:nth-child(n + 3) {
  margin-top: 30px;
}
```
nth-childは子要素の番号などを指定してスタイルを当てるための擬似クラスです。

上のカードだと右2つのカードにだけ```margin-left```を指定して、下2つのカードにだけ```margin-top```を当てるようにしています。

以前は```gap```でなく```nth-child```を使っていたので、もどかしさを感じていました。

似たようなもので```nth-of-type```という擬似クラスもあります。

#### 問題
これだと実は**レスポンシブ**用にコードを書き足す必要があって面倒なんですよね。

しかし「**Grid**」を使えばその必要はないんです。

# Gridでカード実装

次に「**Grid**」でやってみます。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="OJeLdvj" data-pen-title="Untitled" data-user="rei-dev99" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/rei-dev99/pen/OJeLdvj">
  Untitled</a> by rei-dev99 (<a href="https://codepen.io/rei-dev99">@rei-dev99</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

#### ポイント
- 親要素で**Grid**対応、自動調整される列、列行間指定

```
.grid-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 30px;
}
```
```grid-template-columns```プロパティで自動調整される列を定義します。```repeat(auto-fit, minmax(250px, 1fr))```により、コンテナの幅に応じてカードの列数が変動します。各カードの最小幅は```250px```で、最大幅は残りのスペースを均等に分けます。

この記述だけで**レスポンシブ対応**が簡単にできます。

# FlexboxとGridを使い分ける

それぞれ強みは分かれそうです。

### Flexbox

**Flexbox**では下記のようなもので使うと良さそうです。

- ナビゲーションバー
- ツールバー
- メニューバー
- 水平/垂直にコンテンツを並べる(ボタンなど)

テキスト系並べるときに使うと良さそうです。

### Grid

**Grid**では下記のようなもので使うと良さそうです。

- ダッシュボード
- 写真ギャラリー
- 複数のコンテンツエリアを持つレイアウト
- カードレイアウト

画像や文字をもつコンテンツの配置に使うと良さそうです。

# おすすめの学習サイト
Flexboxチートシート

https://www.webcreatorbox.com/tech/css-flexbox-cheat-sheet

Flexboxが理解できるゲーム(すごくおすすめ)

https://flexboxfroggy.com/#ja

Grid理解

https://qiita.com/kura07/items/e633b35e33e43240d363

# おわりに
**FlexBox**だけが正義だと思っていましたが、**Grid**の凄さに気づいてからはもう手放せません。

今後は、**FlexBox**と**Grid**をうまく使い分けて、レイアウトを実現していこうと思います。ぜひ、**Flexbox**と**Grid**を活用して、素敵なレイアウトを実現してみてください。

この記事の内容に不備や改善点があれば、ご指摘いただけると嬉しいです。