ネットソリューション

FlexboxとGridを使い分けよう!基礎編

今年もよろしくお願いします。
ネットソリューション事業部の山下です。

新年最初の更新は、横並びレイアウトの実装におけるFlexboxとGridの私なりの判断基準と各プロパティの解説をお届けします。
私自身、ようやくFlexbox理解したと思った矢先、Gridが登場して「なんだこれ?」と思ったのですが、最近やっとGridもチョットワカルようになってきました。

この横並び、FlexboxGridどっちで実装しよう?

CSSのレイアウト設計で、FlexboxGridをどう使い分けるか悩んだことはありませんか?
例えば、「flexのほうが使い慣れているから、とりあえずflexで」という判断をしていませんか?
そんなとき、以下の基準で使い分けを考えてみましょう。

Flexboxが向いているレイアウト

Flexboxは、子要素が柔軟にサイズを変化する(flexible)ようなレイアウトに向いています。

  • ラベル文字数に応じて横幅が変わる横並びのリスト
    例:タグやボタンのリスト
  • アイテムごとに幅が異なる可変幅のアイテムが並ぶ場合
    例:ナビゲーションメニューやカードレイアウト

Flexboxを使用するときは、子要素のサイズや振る舞いに応じて以下のプロパティを活用します。

  • flex
  • flex-grow
  • flex-shrink

css例

.d-flex {
  display: flex;
  flex-wrap: wrap; // リストが折り返す設定
  gap: 10px 16px; // 子要素間の余白(縦と横)
  &__item {
    &--grow-1 {
      flex-grow: 1; // 子要素が親要素内の空きスペースを埋める
    }
    &--shrink-0 {
      flex-shrink: 0; // 子要素が縮小しない
      width: 100px; // 固定幅指定と併用
    }
  }
}

flex-grow

flex-growは、親要素内の余白をどれだけ埋めるかを指定するプロパティです。
値が大きいほど、その子要素はより多くのスペースを占有します。
デフォルト値は0です。
flex-grow: 1以上を設定した場合その要素は、親要素内の余白を埋めるように広がります。

例えば、2つの子要素が並ぶレイアウトで1つ目の要素を1/3幅、2つ目を2/3幅にしたい場合は、下記のように設定します。

.item1 {
  flex-grow: 1; // 全体の1/3を占有
}
.item2 {
  flex-grow: 2; // 全体の2/3を占有
}

flex-shrink

flex-shrinkは、親要素の幅が不足した場合に子要素がどれだけ縮小するかを指定します。
デフォルト値は1です。
flex-shrink: 0を設定すると子要素は縮小せず、親要素からはみ出す可能性があります。
widthflex-basisと併用することで、縮小を防ぎつつ意図したサイズ感を維持できます。

Flexboxの注意点

Flexboxgapを使用する際には、対応ブラウザやOSバージョンに注意が必要です。
特に、iOS 14.4以前では、Flexboxでのgapプロパティがサポートされていません
そのため、プロジェクトで古いバージョンのOSをサポートする必要がある場合、gapの代替手段としてmarginを使用して余白を設定するなどの代替手段をとる必要があります。
※iOS14.4は2021年のバージョンなので早々ないとは思いますが、検証機のOSバージョンアップはその性質上、意図的に止められている場合もあるので要注意です。

Gridが向いているレイアウト

Gridは、格子状(グリッド状)に子要素を配置するようなレイアウトに向いています。
子要素の幅や位置が明確に決まっているレイアウトに向いています。

  • 均等幅の横並びレイアウト
  • カラム数や行数が決まっているレイアウト
    例:画像ギャラリーや商品一覧など

css例

.d-grid {
  display: grid;
  grid-template-columns: 1fr 1fr; // 横並びに均等幅2カラム
  gap: 10px 16px; // 子要素間の余白(縦と横)
}

grid-template-columns

grid-template-columnsは、グリッドの列の幅を定義するプロパティです。

fr(fraction unit)

fr(fraction unit)は、利用可能な空きスペースを分割する単位です。
例えば、以下の例では

.grid1 {
  grid-template-columns: 1fr 2fr;
}
  • 1frの列は、全体の空きスペースの1単位分を使用します。
  • 2frの列は、全体の空きスペースの2単位分を使用します。

つまり、1:2の比率で列が配置されます。

frは固定値と組みわせることでより柔軟にレイアウトを実装することができます。
例えば下記のようにすると、左側を固定値にしたうえで右側が親要素の幅に沿って縮小するように設定することができます。

.grid1 {
  grid-template-columns: 200px 1fr; // 左側は常に200px 右側は親要素の余白を埋めるように広がる
}

repeat()で簡潔に指定

同じ幅の列が複数ある場合、repeat()を使用すると簡潔に書くことができます。

.grid1 {
  grid-template-columns: repeat(2, 1fr); // 均等幅の列を2つ作成
}

上が1列、下が2列これなーに(で実装する)?

格子状じゃないのでこれは、Flexbox!とおもいきや、
このようなレイアウトもGridで実装することができます。

このカラムは横1列

このカラムは横2列

このカラムは横2列

css例

.d-grid-sample {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  text-align: center;
  gap: 16px;
}

.d-grid-sample > * {
  border: 1px solid #000;
  padding: 16px;
}

.d-grid-sample__full {
  grid-column: span 2; //この要素は横に2列分を占める
}

grid-column

grid-columnは子要素がグリッド内で横方向にどれだけの列を占めるかを指定します。
grid-column: span 2と設定することで、その要素が2列分を占めるようになります。
span の後に数字を指定することで、横方向にその数分の列を広げることができます。


以上となります。
レイアウトを再現する際のCSS実装には絶対的な正解はないと思いますが、実装コストや可読性の面で「こうしたほうが良い」といったアプローチは確かに存在します。
状況や要件に応じて最適な方法が変わるため、今回ご紹介した内容が一つの判断基準として、少しでも皆様のお役に立てれば幸いです。

今年もよろしくお願いいたします。

Webの進化の速さにアップアップですがなんとか喰らいついていきたい。

山下 X@Frencel_ns

フロントエンドエンジニア
フレームワーク頑張りたい人
モンハンワイルズではキアヌ・リーブス似のイケオジでプレイしたい

好きなモンスターハンターの武器

双剣・狩猟笛

mail お問い合わせ

ご覧いただきありがとうございます。
当メディアへのご質問や各事業部へのお仕事のご相談がありましたら、お気軽にお問い合わせください。

article 過去記事