📏

[CSS]Flexboxを入れ子にすると変な隙間ができてしまう

2021/12/14に公開

この現象に言及している記事が少ないため、解決法と隙間ができる理由を取りまとめておこうかと思います。

Flexboxを入れ子にするとできる変な隙間

下記のような、親Flexコンテナ>親Flexアイテム>子Flexコンテナ>子Flexアイテム、と二重に入れ子になったFlexboxがあります。

<div class="parent-container">
  <div class="parent-item">
    <div class="child-container">
      <div class="child-item">
        あいうえお
      </div>
    </div>
  </div>
</div>
  1. .parent-containerflex-directioncolumn方向に
  2. .parent-containerflex-wrapwrap
  3. .child-itemflex-basisで表示幅を100%よりも小さい値に
.parent-container {
  display: flex;
  flex-direction: column; /* 1. */
  flex-wrap: wrap; /* 2. */
}
.parent-item {
}
.child-container {
  display: flex;
}
.child-item {
  flex-basis: 80%; /* 3. */
}

上記の条件を満たす場合、Flexboxの下の部分に意図しない隙間が生じることがあります。
下記サンプルの赤い部分がそうです。わかりやすいように各ボックスに背景色をつけています。

親コンテナにflex-wrap: wrap;が使用されている場合に遭遇しやすくなるかと思います。
フレームワークによっては、Flexboxのユーティリティクラスにデフォルトで flex-wrap: wrap; が設定されている場合もあり、遭遇率が高くなります。
私の愛用している Quasar Framework がまさしくそれです。

解決方法

端的に言えば、親コンテナの flex-wrap: wrap; を削除、もしくは flex-wrap: nowrap; で上書きすれば隙間は生じなくなります。

.parent-container {
  display: flex;
  flex-direction: column; /* 1. */
  /* flex-wrap: wrap; */ /* 2. */
}
.parent-item {
}
.child-container {
  display: flex;
}
.child-item {
  flex-basis: 80%; /* 3. */
}

隙間ができる理由

仕様書を読み込みましたが、私の頭では完全な理解には及びませんでした。
ただ、下記のようなプロセスで隙間ができてしまっていると想像できます。

  1. 最初は、親コンテナのflex-directionは初期値であるrowであると解釈される?
  2. その状態で、子コンテナのサイズが計算される
  3. ここで初めて、親コンテナのflex-directioncolumnとして、親コンテナのサイズが計算される
  4. 親コンテナのサイズが算出されたことによって、子コンテナのサイズがもっと小さくなり得るとしても、子コンテナのサイズは再計算されないため、無用な隙間ができたままになる

私なりに解釈した結果なので間違っている可能性はあります。(ご指摘お待ちしております。)

これを検証するために、親コンテナの flex-directionrow のものと column のものを2つ用意し、それぞれの子アイテムの flex-basis を同時に変更できるものを作成しました。

子アイテムの flex-basis の値を同時に変更してみると、親コンテナの flex-directionrow のときに計算された高さが、そのまま flex-directioncolumn の場合の高さに適用されています。
これが、親コンテナが flex-direction: row; である前提で子コンテナの高さが計算されている証拠と言っても良いでしょう。

繰り返しますが、仕様書の正確な理解には至っておりませんので、私なりの解釈になります。

参考

この現象に2~3年付き合い続けてきて、同じ現象について言及されたもの、本当にこれしか見つからなかった。
探し方が悪かったのかもしれない。

Discussion