FirefoxでFlexBoxの縦横組み合わせを使うにはmin-height:0が必要

2019年5月16日

FlexBoxについての解説ページは多々あるのだが、これについて記述しているページはほとんど見ない。FirefoxでFlexBoxを縦横組み合わせて使うには、min-height:0(もしくはmin-width:0)の指定が必須ということだ。

Chromeでは必要無いのだが、これはFirefoxのバグではなく、Firefoxの方がCSSの仕様に対して厳格だからである。Chromeの方が余計なお世話しているがために、うまく表示されるのだ。

状況

具体的な状況は以下だ。トップに縦方向のFlexBoxを置き、その中に横方向のFlexBoxを置く。この横方向のFlexBoxについて、ChromeとFirefoxの動作が違ってしまう。

※この動作を確認したのは2018/11のことなのだが、2019/5現在再度確認してみると、Chrome(74.0.3729.157)はFirefoxと同じ動きになっているようだ。

<!DOCTYPE html> 
<html style="margin:0; height: 100%">
<body style="margin:0; height: 100%">


<!-- 外側の縦方向のFlex-Container -->
<div style="display: flex; flex-direction: column; height: 100%">

   <div >top 0<br>top 1<br>top 2<br></div>

   <!-- 内側の横方向のFlex-Container -->
   <div style="display: flex; flex-direction: row; width: 100%;">

      <div style="overflow: auto;">
         <div >middle-left 0<br>middle-left 1<br>middle-left 2<br>middle-left 3<br>middle-left 4<br>middle-left 5<br>middle-left 6<br>middle-left 7<br>middle-left 8<br>middle-left 9<br></div>
      </div>

      <div style="overflow: auto;">
         <div >middle-center 0<br>middle-center 1<br>middle-center 2<br>middle-center 3<br>middle-center 4<br>middle-center 5<br>middle-center 6<br>middle-center 7<br>middle-center 8<br>middle-center 9<br></div>
      </div>

   </div>

   <div >bottom 0<br>bottom 1<br>bottom 2<br></div>
</div>


</body>
</html>
</body>
</html>

Chromeではこうなる(2019/5時点のバージョンではFirefoxと同じ動きになるようだ)。

Firefoxではこうなる。

なお、各Flex Itemにflexを入れてみても状況は変わらない。

<!DOCTYPE html> 
<html style="margin:0; height: 100%">
<body style="margin:0; height: 100%">


<!-- 外側の縦方向のFlex-Container -->
<div style="display: flex; flex-direction: column; height: 100%">

   <div syle="flex: 0 0 auto">top 0<br>top 1<br>top 2<br></div>

   <!-- 内側の横方向のFlex-Container -->
   <div style="flex: 1 1 auto; display: flex; flex-direction: row; width: 100%">

      <div style="overflow: auto;">
         <div >middle-left 0<br>middle-left 1<br>middle-left 2<br>middle-left 3<br>middle-left 4<br>middle-left 5<br>middle-left 6<br>middle-left 7<br>middle-left 8<br>middle-left 9<br></div>
      </div>

      <div style="overflow: auto;">
         <div >middle-center 0<br>middle-center 1<br>middle-center 2<br>middle-center 3<br>middle-center 4<br>middle-center 5<br>middle-center 6<br>middle-center 7<br>middle-center 8<br>middle-center 9<br></div>
      </div>

   </div>

   <div syle="flex: 0 0 auto">bottom 0<br>bottom 1<br>bottom 2<br></div>
</div>


</body>
</html>
</body>
</html>

FireFoxでスクロールバーを出現させるには、以下のようにmin-heightの指定を行わないといけない。

   <!-- 内側の横方向のFlex-Container -->
   <div style="display: flex; flex-direction: row; width: 100%; min-height:0">

Firefoxではみ出してしまう理由(仕様通り)

以下のようなQ&Aがあり、理由が説明されている。結論としては、Firefoxの動きの方が正しいので「min-height:0」を指定せよということだ。

CSSの仕様を説明してくれているのだが、今回の状況に合わせて説明し直せば、以下になる。

外側の三つのFlex Itemはどれもデフォルトの「overflow: visible」になっているのだが、この場合、「min-height: auto」がデフォルトとして使われる。

従って、この縦に並ぶ三つのFlex Itemの自然な高さが採用されるので、はみ出してしまうはずなのである。

しかし、真ん中の横方向のFlex Itemである二番目のFlex Containerには、「overflow: auto」を指定したくはない。そうしてしまうと、場合によってはこのFlex Container全体にスクロールバーがついてしまう可能性があるからだ。

だから、「overflow: visible」の場合のデフォルトである「min-height: auto」を上書きする他はない。通常は「min-height: 0」とすればよい。

Chromeの仕様に沿わない動き

Chromeの仕様に沿わない動きについては解説がある。

Since at least 2017, it appears that Chrome is either (1) reverting back to the min-width: 0 / min-height: 0 defaults, or (2) automatically applying the 0 defaults in certain situations based on a mystery algorithm. (This could be what they call an intervention.) As a result, many people are seeing their layout (especially desired scrollbars) work as expected in Chrome, but not in Firefox / Edge. This issue is covered in more detail here: flex-shrink discrepancy between Firefox and Chrome

どういうわけか、2017年にChromeはmin-height:0に戻ったか、奇妙なアルゴリズムで特定の状況にmin-height:0にしているようだ。この結果、多くの人が、特にスクロールバーについてChromeでは動作するのに、Firefox/Edgeでは動作しないという状況に出くわした。この詳細はflex-shrink discrepancy between Firefox and Chromeにある。

※2019/5の時点では、仕様通りの動きに戻ったように思われる。