flex アイテムの幅と flex プロパティの関係

メモ:  Category:html

サイトのデザイン変更に向けて久しぶりにコーディングしてみたところ、「 flexbox うまく使えていない?思った幅にならない?」としっかり理解できていなかったので、改めてまとめてみます。

flex アイテムの幅と余白

今回確認していく部分はレイアウトに関わる部分で、主に flex-grow (または flex )プロパティの部分になります。

flex プロパティは、次の3つのプロパティのショートハンドで flex-shrink と flex-basis は省略することができます。

  • flex-grow
  • flex-shrink
  • flex-basis

flex-shrink と flex-basis を省略した場合、 flex-shrink , flex-basis は次の値が与えられ「flex: 1 1 0」と同じ指定になります。

  • flex-shrink:1
  • flex-basis:0

flexbox は、 display: flex を指定した親要素の「 flex コンテナ」と、その中にある子要素の「 flex アイテム」で構成されます。

flexbox の基本

上の図のように余白ができる場合、 flex-grow (または flex )の設定を行うと flex-grow の設定にしたがって余白を「 flex アイテム」に分配する仕組みになっています。

例えば、次の図のように flex アイテムに flex: 1 と flex: 2 が指定してあるとします。この場合、 flex-grow の合計で余白を分割し、 flex-grow で指定したように分割した余白が分配されます。

余白の分配ルール

各 flex アイテムに与えられるサイズは、 flex-basis の設定も影響を与えており flex プロパティに1つだけ値を指定した場合 flex アイテムの幅を0として計算されます。

flex アイテムの幅はどう計算される

それでは、実際の計算方法について見ていきます。例えば、 flex コンテナの幅が 1200px として、 flex アイテム「A」に flex-grow の値を 1 、 flex アイテム「B」に flex-grow の値を 2 と指定したとします。その場合、 flex アイテムの幅は次のような計算になります。

flex アイテム「A」と「B」
Aの幅 = A自身のコンテンツ幅 + (1 × (1200px – AとBのコンテンツ幅の合計) ÷ (Aのflex-grow + Bのflex-grow))
Bの幅 = B自身のコンテンツ幅 + (2 x (1200px – AとBのコンテンツ幅の合計) ÷ (Aのflex-grow + Bのflex-grow))

flex アイテム「A」,「B」にショートハンドで flex:1 , flex: 2 と指定した場合、 flex-basis に 0 が指定されたものとみなされ、コンテンツ幅は 0 として計算されます。

Aの幅 = 0 + (1 × (1200px – 0) ÷ (1 + 2)) = 400px
Bの幅 = 0 + (2 × (1200px – 0) ÷ (1 + 2)) = 800px

実装してみると、きれいに幅が分配されていることが確認できます。

次に flex-basis に幅の指定や auto が指定された場合を見ていきます。例えば、flex アイテム「A」に300px、.flex-2には600pxを指定してみます。その場合、 flex アイテムの幅は次のような計算になります。

Aの幅 = 300px + (1 × (1200px – (300px + 600px)) ÷ (1 + 2)) = 400px
Bの幅 = 600px + (2 × (1200px – (300px + 600px)) ÷ (1 + 2)) = 800px

CSS の flex プロパティは次のような指定になります。

.flex-item-A { flex: 1 1 300px; }
.flex-item-B { flex: 2 1 600px; }

続けて flex-basis に auto が指定された場合を確認していきます。次の画像は、 flex アイテムに何も指定していない状態でflex アイテムのサイズを確認したものです。画面上、flex アイテムが2つありどちらも幅が 42.69 になっています。

flex アイテムの幅

この flex アイテムに次のスタイルを適用します。

.flex-item-A { flex: 1 1 auto; }
.flex-item-B { flex: 2 1 auto; }

flex-basis に auto を指定すると自動的にベースとなる flex アイテムの幅や高さを使用して計算するようになります。この場合、幅を 42.69 として次のように計算されます。※注意: flex コンテナの幅を 1880px としています。

Aの幅 = 42.69px + (1 × (1880px – (42.69px + 42.69px)) ÷ (1 + 2)) = 640.89px
Bの幅 = 42.69px + (2 × (1880px – (42.69px + 42.69px)) ÷ (1 + 2)) = 1239.11px
flex-basis に auto を指定した結果

ここまでで、flex アイテムの幅がどのように計算されるのかなんとなく見えてきました。実際に2カラムのレイアウトや3カラムのレイアウトを作りたい場合、閲覧サイズに応じて幅を変動させたい部分に flex プロパティを設定することで柔軟なレイアウトが実現できそうです。

おまけ

次の画像は、2カラムレイアウトをイメージした記述となります。

2カラムレイアウトの例

左の flex アイテムは固定幅 150px としてあり右の flex アイテムのみ flex: 1 としています。こうすることで余白部分がすべて右の flex アイテムに分配されコンテナいっぱいの2カラムレイアウトが実現できます。また、画面幅が変更されてもそれに追従して右の flex アイテムのサイズが変更されます。

bluenote by BBB