Flexbox で要素を横並びにしたとき、「この要素だけ広げたい」「画面が狭くなったら縮めたい」と思ったことはないでしょうか。flex アイテムの幅の伸び縮みを決めているのが、flex-grow・flex-shrink・flex-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;
}
注意したいのは、flex-grow が分配するのは「余ったスペース」だという点です。アイテムの幅そのものが比率になるわけではありません。基準サイズ(flex-basis)が異なれば、伸びたあとの最終的な幅の比率も変わります。上のデモで flex-basis: 0 を指定しているのは、基準サイズをゼロにそろえることで、最終的な幅をきれいに 1:2:1 の比率に見せるためです。
flex-shrink:スペースが足りないときの縮み方を決める
flex-shrink は flex-grow とは逆で、アイテムの合計幅がコンテナに収まりきらないときに、どの割合で縮むかを決めます。初期値は 1 で、デフォルトではすべてのアイテムが縮んで、はみ出さないように収まります。
値を 0 にすると、そのアイテムは縮まなくなります。たとえばサイドのアイコンやボタンは縮めず、本文エリアだけを縮めたい、といった調整に使えます。次の例では、左のラベルを flex-shrink: 0 で固定し、右のテキスト部分だけが縮むようにしています。
.label {
flex-shrink: 0; /* 縮まない(幅を保つ) */
width: 120px;
}
.text {
flex-shrink: 1; /* スペースが足りなければ縮む(初期値) */
}
アイテムが意図せず潰れてしまうときは、この flex-shrink: 0 を指定すると、その要素だけ縮まないように固定できます。
flex-basis:伸縮する前の基準サイズを決める
flex-basis は、伸び縮みする前の基準となる幅です。width と似ていますが、flex アイテムでは flex-basis が優先され、ここを起点に flex-grow や flex-shrink による調整が加わります。
初期値は auto で、このときアイテムの中身(コンテンツ)や width の指定に応じた幅が基準になります。flex-basis: 200px のように長さを指定すれば、その幅を起点に伸縮します。flex-basis: 0 にすると基準サイズがゼロになり、前述のとおり最終的な幅が flex-grow の比率そのままで決まります。
flex ショートハンドでまとめて書く
実際のコードでは、3つを個別に書くより flex ショートハンドでまとめて書くのが一般的です。値は flex-grow・flex-shrink・flex-basis の順に並べます。
.item {
/* flex-grow: 1; flex-shrink: 1; flex-basis: 200px; と同じ */
flex: 1 1 200px;
}
よく使う組み合わせには、次のような書き方があります。それぞれが3つのプロパティのどの値に対応するかを表にまとめました。
| 書き方 | 意味(grow / shrink / basis) |
|---|---|
flex: 1 | 1 / 1 / 0%。余白を均等に分け合って伸びる |
flex: auto | 1 / 1 / auto。中身の大きさを尊重しつつ伸縮する |
flex: none | 0 / 0 / auto。伸びも縮みもしない(サイズ固定) |
flex: 1 のように値を1つだけ書いた場合、それは flex-grow の値になり、flex-shrink は 1、flex-basis は 0% が補われます。
flex: 1 がなぜ均等幅になるのか
複数のアイテムすべてに flex: 1 を指定すると、横幅がぴったり均等になります。これは flex: 1 が flex: 1 1 0% の意味だからです。
ポイントは flex-basis が 0% になっている点です。基準サイズがゼロなので、アイテムの幅は「中身の大きさ」ではなく、余ったスペースを flex-grow の比率で分けた結果だけで決まります。すべてのアイテムが flex-grow: 1 なら、スペースは 1:1:1…と等しく分配され、結果として中身の文字数が違っても幅は均等になる、というわけです。
一方 flex: auto(1 1 auto)は flex-basis が auto のため、中身の大きい要素ほど基準サイズが大きくなり、幅は均等になりません。「中身に関係なくきっちり均等に並べたい」なら flex: 1、「中身の量を反映しつつ余白を埋めたい」なら flex: auto と使い分けると覚えておくとよいでしょう。
まとめ
flex アイテムの幅の伸縮は、3つのプロパティで決まります。
flex-grow:余ったスペースを受け取って伸びる割合(初期値 0)flex-shrink:足りないときに縮む割合(初期値 1、0で縮まない)flex-basis:伸縮する前の基準サイズ(初期値 auto)
ふだんは flex: 1 や flex: auto といったショートハンドで十分です。均等幅にしたいときは flex: 1 を、サイズを固定したいときは flex: none や flex-shrink: 0 を思い出してください。まずは横並びのアイテムに flex: 1 を付けて、伸縮の動きを体感してみましょう。