Flexbox を使ったレイアウトで避けて通れないのが「flex-grow」「flex-shrink」「flex-basis」。
でも、それぞれの役割がややこしく感じることはありませんか?

この記事では、これら3つのプロパティの意味や違い、実際の使い方を図解・コード付きでやさしく解説します。
Flexboxの挙動を自在にコントロールしたい方は、ぜひ最後までご覧ください!

この記事で分かること
  • display: flex;の中で子要素がどう伸びたり縮んだりするかが分かる
  • flex-basis、flex-grow、flex-shrinkの使い方を理解できる
  • flex: 1 などの省略した書き方を使いこなせるようになる

基本のイメージ

前提として、親要素にdisplay: flex;を指定すると親要素が「フレックスコンテナ」、子要素が「フレックスアイテム」になります。

以下はフレックスアイテムが横に並ぶイメージです。

<div class="item-wrapper">
  <div class="item1">フレックスアイテム1</div>
  <div class="item2">フレックスアイテム2</div>
  <div class="item3">フレックスアイテム3</div>
</div>
.item-wrapper {
  display: flex;
}

See the Pen flex-item default by 黒田こうすけ (@uuygwojs-the-bashful) on CodePen.

このとき、親要素の幅に対して、各子要素がどう伸びたり縮んだりするのかを決めるのが以下の3つのプロパティです。

  • flex-basis:要素の「初期サイズ(基準)」を決める
  • flex-grow:余ったスペースを「どれくらい伸ばして埋めるか」
  • flex-shrink:足りないスペースのときに「どれくらい縮むか」

Flexアイテムの挙動を決める3つのプロパティ

この章では、フレックスアイテムのレイアウトをコントロールする3つのプロパティについて意味と使い方を具体的に解説していきます。

flex-basis : 基準となるサイズ

flex-basis は、フレックスアイテムの“初期サイズ”を指定するプロパティです。

.item-wrapper {
  display: flex;
}
.item1 {
  flex-basis: 100px;
}
.item2 {
  flex-basis: 100px;
}
.item3 {
  flex-basis: 100px;
}

See the Pen flex-basis by 黒田こうすけ (@uuygwojs-the-bashful) on CodePen.

これは、「このアイテムは横幅100pxですよ」と指定している状態です。子要素ごとに指定できます。

  • width よりも flex-basis が優先される
  • 初期値は auto で、その場合は内容や width によってサイズが決まる

flex-grow : 余ったスペースの分け合い

親要素に余ったスペースがあるときに、どのアイテムがどれくらい「伸びるか」を決めます。
「grow」の日本語訳は「育つ」なので、その名の通りflexアイテムが育つイメージですね。

.item-wrapper {
  display: flex;
}
.item1 {
  flex-grow: 1;
}
.item2 {
}
.item3 {
}

See the Pen flex-grow-1 by 黒田こうすけ (@uuygwojs-the-bashful) on CodePen.

item1のflex-growの値は1、item2とitem3は指定していないので初期値の0が指定されています。
item2と3は伸びず、親要素の余白を埋める形でitem1が伸びています。

.item-wrapper {
  display: flex;
}
.item1 {
  flex-grow: 1;
}
.item2 {
  flex-grow: 2;
}
.item3 {
  flex-grow: 0;
}

See the Pen flex-grow by 黒田こうすけ (@uuygwojs-the-bashful) on CodePen.

上記の例ではitem1のflex-growの値は1、item2は2、item3は0を指定しています。
仮に親要素の余白が300pxあれば、item1は100px、item2は200px伸び、item3は伸びません。

この時、flex-growの値は子要素の幅を示しているわけではないという点に注意が必要です。
親の中の余白をflex-growの比率に従ってそれぞれの子要素に分配するイメージです。

子要素の幅 = 基準となるもともとの幅 + flex-growで伸びる幅

  • 子要素の幅 = 基準となる幅 + flex-growで伸びる幅
  • 初期値は0で、余白があっても伸びない

flex-shrink : スペースが足りないときの縮み具合

flex-shrink は、子要素の合計が親要素の幅を超えてしまった時に、どれくらい「縮むか」を指定します。
「shrink」の日本語訳は「縮む」です。そのままですね。

親要素の幅を超えてしまった分に対して、flex-shrinkで指定した比率に従って子要素を縮めます。

.item-wrapper {
  display: flex;
}
.item1 {
  flex-basis: 50%;
  flex-shrink: 0;
}
.item2 {
  flex-basis: 50%;
  flex-shrink: 0;
}
.item3 {
  flex-basis: 50%;
  flex-shrink: 0;
}

See the Pen flex-shrink by 黒田こうすけ (@uuygwojs-the-bashful) on CodePen.

flex-shrink: 0;は、子要素を縮めないことを意味します。
上記の場合、flex-shrink: 0;で各子要素の横幅を50%としているため、横幅の合計が150%となり、親要素を50%超えてしまっています。

ここで、item1のflex-shrinkを2、item2を3、item3を0とすると、、、

.item-wrapper {
  display: flex;
}
.item1 {
  flex-basis: 50%;
  flex-shrink: 2;
}
.item2 {
  flex-basis: 50%;
  flex-shrink: 3;
}
.item3 {
  flex-basis: 50%;
  flex-shrink: 0;
}

See the Pen flex-shrink2 by 黒田こうすけ (@uuygwojs-the-bashful) on CodePen.

超えてしまった50%のうち、item1が20%、item2が30%縮みます。
flex-growと同じく、親要素を超えた分をflex-shrinkの比率に従ってそれぞれの子要素に分配して、もともとの横幅から引く形でサイズを計算します。

  • item1の幅 = 50%(もともとの横幅) ー 20%(flex-shrinkで指定した縮む幅)
  • item2の幅 = 50%(もともとの横幅) ー 30%(flex-shrinkで指定した縮む幅)
  • item3の幅 = 50%(もともとの横幅) ー 0(flex-shrink: 0;)

では仮に、すべての子要素でflex-shrinkを指定しない場合どうなるでしょうか。

.item-wrapper {
  display: flex;
}
.item1 {
  flex-basis: 50%;
}
.item2 {
  flex-basis: 50%;
}
.item3 {
  flex-basis: 50%;
}

See the Pen flex-shrink3 by 黒田こうすけ (@uuygwojs-the-bashful) on CodePen.

flex-shrinkの初期値は1です。
子要素すべてでflex-shrinkを指定していない場合、子要素は均等に縮み親要素にぴったり納まります。

  • 子要素の幅 = 基準となる幅 - flex-shrinkで縮む幅
  • 初期値は1

3つのflexプロパティを「flex」1つで書く

「flex」というプロパティで、「flex-grow」「flex-shrink」「flex-basis」の3つをまとめて書くことができます。

.item {
  flex: 1 1 200px; /* grow shrink basis */
}

これは、flex-grow: 1; flex-shrink: 1; flex-basis: 200px;の省略形です。

ちなみに、このように複数のプロパティを省略して記載する方法をCSSショートハンドといいます。

よくある指定の例
flex: 1;

grow=1,shrink=1,basis=0(等分に伸びる)

flex: 0 1 auto;

伸びないが縮む、初期サイズはauto(flex: initial;とも書ける)

flex: 1 1 auto;

自由に伸び縮みする(flex: auto;とも書ける)

flex: 0 0 auto;

伸びも縮みもしない。固定サイズ(flex: none;とも書ける)

よくある質問(FAQ)

widthとflex-basis、どちらが優先される?

flex-basisが優先されます。
Flexboxを使っている場合、widthを指定してもflex-basisがautoでない限り、それは無視されます。

すべての子要素を等分割したいときは?

flex: 1;を指定します。
すべての子要素にflex: 1;と指定するだけで、余白を含めて等しく伸びるカラムが作れます。

flex-basisを指定しても効かないのはなぜ?

flex-basisを含むflexのプロパティは、親要素がdisplay: flexになっている必要があります。
また、flexのショートハンドでflex-basisが上書きされているケースもあるため、flexプロパティの値も確認しましょう。

まとめ

プロパティ意味初期値
flex-grow伸びる力0
flex-shrink縮む力1
flex-basis基準のサイズauto

これらのプロパティを使いこなすことで、柔軟で美しいレイアウトを作りましょう!

参考にしたサイト

MDNの公式サイトを参考にしています。詳しく知りたい方はこちらをご覧ください。

カスケーディングスタイルシート > flex