1. ホーム
  2. CSS

【CSS】flex-grow・flex-shrink・flex-basis の使い方|flexアイテムの幅の伸縮を制御する

Share

Flexbox で要素を横並びにしたとき、「この要素だけ広げたい」「画面が狭くなったら縮めたい」と思ったことはないでしょうか。flex アイテムの幅の伸び縮みを決めているのが、flex-growflex-shrinkflex-basis という3つのプロパティです。この記事では、それぞれの役割と、まとめて書ける flex ショートハンドの使い方を、初心者向けに動くデモつきで解説します。flex: 1 がなぜ均等幅になるのかも説明します。

3つのプロパティは「flexアイテムの幅」を決める

display: flex を指定した親要素(flex コンテナ)の中に並ぶ子要素を、flex アイテムと呼びます。この flex アイテムの幅を、コンテナの広さに応じてどう伸び縮みさせるかを決めるのが、次の3つのプロパティです。いずれも flex アイテム側(子要素)に指定します。

プロパティ役割
flex-grow余ったスペースをどの割合で受け取って伸びるかを決める
flex-shrinkスペースが足りないときにどの割合で縮むかを決める
flex-basis伸縮する前の基準となる幅を決める

「基準サイズ(flex-basis)を起点に、余れば flex-grow の割合で伸び、足りなければ flex-shrink の割合で縮む」という関係になっています。まずは伸びる側の flex-grow から見ていきましょう。

flex-grow:余ったスペースの分け方を決める

flex-grow は、コンテナに余ったスペースを、各アイテムがどの割合で受け取って伸びるかを表す数値です。初期値は 0 で、このときアイテムは伸びません。1 以上の値を指定すると、その比率に応じて余白を分け合って伸びます

たとえば3つのアイテムにそれぞれ 1 / 2 / 1 を指定すると、余ったスペースを 1:2:1 の割合で分配します。下のデモで実際の幅の違いを確認してみてください。真ん中のアイテムだけ広く伸びているのが分かります。

<div class="flex">
  <div class="item grow1">flex-grow: 1</div>
  <div class="item grow2">flex-grow: 2</div>
  <div class="item grow1">flex-grow: 1</div>
</div>
body {
  margin: 0;
  font-family: sans-serif;
}

.flex {
  display: flex;
  gap: 8px;
  padding: 16px;
}

.item {
  /* flex-basis(基準サイズ)を 0 にすると、横幅は flex-grow の比率で決まる */
  flex-basis: 0;
  padding: 24px 8px;
  background: #4f46e5;
  color: #fff;
  text-align: center;
  border-radius: 6px;
  box-sizing: border-box;
}

/* 余白を 1 の割合で受け取る */
.grow1 {
  flex-grow: 1;
}

/* 余白を 2 の割合で受け取る(grow1 の 2 倍の幅になる) */
.grow2 {
  flex-grow: 2;
}
Preview

注意したいのは、flex-grow が分配するのは「余ったスペース」だという点です。アイテムの幅そのものが比率になるわけではありません。基準サイズ(flex-basis)が異なれば、伸びたあとの最終的な幅の比率も変わります。上のデモで flex-basis: 0 を指定しているのは、基準サイズをゼロにそろえることで、最終的な幅をきれいに 1:2:1 の比率に見せるためです。

flex-shrink:スペースが足りないときの縮み方を決める

flex-shrinkflex-grow とは逆で、アイテムの合計幅がコンテナに収まりきらないときに、どの割合で縮むかを決めます。初期値は 1 で、デフォルトではすべてのアイテムが縮んで、はみ出さないように収まります。

値を 0 にすると、そのアイテムは縮まなくなります。たとえばサイドのアイコンやボタンは縮めず、本文エリアだけを縮めたい、といった調整に使えます。次の例では、左のラベルを flex-shrink: 0 で固定し、右のテキスト部分だけが縮むようにしています。

style.css
.label {
  flex-shrink: 0; /* 縮まない(幅を保つ) */
  width: 120px;
}

.text {
  flex-shrink: 1; /* スペースが足りなければ縮む(初期値) */
}

アイテムが意図せず潰れてしまうときは、この flex-shrink: 0 を指定すると、その要素だけ縮まないように固定できます。

flex-basis:伸縮する前の基準サイズを決める

flex-basis は、伸び縮みする前の基準となる幅です。width と似ていますが、flex アイテムでは flex-basis が優先され、ここを起点に flex-growflex-shrink による調整が加わります。

初期値は auto で、このときアイテムの中身(コンテンツ)や width の指定に応じた幅が基準になります。flex-basis: 200px のように長さを指定すれば、その幅を起点に伸縮します。flex-basis: 0 にすると基準サイズがゼロになり、前述のとおり最終的な幅が flex-grow の比率そのままで決まります。

flex ショートハンドでまとめて書く

実際のコードでは、3つを個別に書くより flex ショートハンドでまとめて書くのが一般的です。値は flex-growflex-shrinkflex-basis の順に並べます。

style.css
.item {
  /* flex-grow: 1; flex-shrink: 1; flex-basis: 200px; と同じ */
  flex: 1 1 200px;
}

よく使う組み合わせには、次のような書き方があります。それぞれが3つのプロパティのどの値に対応するかを表にまとめました。

書き方意味(grow / shrink / basis)
flex: 11 / 1 / 0%。余白を均等に分け合って伸びる
flex: auto1 / 1 / auto。中身の大きさを尊重しつつ伸縮する
flex: none0 / 0 / auto。伸びも縮みもしない(サイズ固定)

flex: 1 のように値を1つだけ書いた場合、それは flex-grow の値になり、flex-shrink1flex-basis0% が補われます。

flex: 1 がなぜ均等幅になるのか

複数のアイテムすべてに flex: 1 を指定すると、横幅がぴったり均等になります。これは flex: 1flex: 1 1 0% の意味だからです。

ポイントは flex-basis0% になっている点です。基準サイズがゼロなので、アイテムの幅は「中身の大きさ」ではなく、余ったスペースを flex-grow の比率で分けた結果だけで決まります。すべてのアイテムが flex-grow: 1 なら、スペースは 1:1:1…と等しく分配され、結果として中身の文字数が違っても幅は均等になる、というわけです。

一方 flex: auto1 1 auto)は flex-basisauto のため、中身の大きい要素ほど基準サイズが大きくなり、幅は均等になりません。「中身に関係なくきっちり均等に並べたい」なら flex: 1、「中身の量を反映しつつ余白を埋めたい」なら flex: auto と使い分けると覚えておくとよいでしょう。

まとめ

flex アイテムの幅の伸縮は、3つのプロパティで決まります。

  • flex-grow:余ったスペースを受け取って伸びる割合(初期値 0)
  • flex-shrink:足りないときに縮む割合(初期値 1、0 で縮まない)
  • flex-basis:伸縮する前の基準サイズ(初期値 auto)

ふだんは flex: 1flex: auto といったショートハンドで十分です。均等幅にしたいときは flex: 1 を、サイズを固定したいときは flex: noneflex-shrink: 0 を思い出してください。まずは横並びのアイテムに flex: 1 を付けて、伸縮の動きを体感してみましょう。

参考リンク