LoginSignup
4

More than 3 years have passed since last update.

posted at

updated at

Flexboxで「width:0」にしてうまくいく場合について研究してみた

こちらは、 CAMエンジニア Advent Calendar 2019 8日目の記事です。
https://qiita.com/advent-calendar/2019/cam-inc
昨日は @ruman さんの
JavaScriptの基本文法
でした。

自分もフロントエンドをやっていて、「なんだこれ!」となったところだったので、
非常におもしろかったです!
詳しくは記事見てください笑


今回は、flex boxをつかってレイアウトしているときに、
「なぜか width: 0 をつけないとうまくできないなぁ」
って思う事件に何度も遭遇したので、
あらためて、flex boxとはなんぞやも含めて研究(大袈裟ですがw)してみました。

基本的なところは
こちらのサイトが個人的に一番わかりやすいので、参考にしてみてください。

最後まで、読むとガッカリするかもなので、先に結論を述べると、問題の原因は解明しきれませんでした。
ただし、原因究明のためにいろいろ調べた結果、学びが深かったので是非知ってもらいたい!!
では、研究開始です!

どんなときに、width: 0が必要になるの?

実際に業務で困ったのは、こんな感じのレイアウトを組んで行くときでした。
サンプル.png
問題の原因は、display: flexなっている要素が入れ子になっているとき、
内側の要素にflex-basis: 0が効かないということです。
(背景の黒い要素も、緑の帯と写真も横並びにしたい)

width: 0を指定しないとがっつり画面の幅をはみ出してくる
スクリーンショット 2019-12-08 6.00.21.png

そもそもflex-basisとは

問題を解決するため、ここからちゃんとしらべてみました。

W3Cの仕様書をみると要素には写真のようにいろいろな方向に対して定義がされています。

flex-basisは、main axis方向に対する幅を指定しているのです。
さらに、main-axisは、flex-directionrowにするかcolumnにするかでその方向が変わります。
(むしろ、flex-directionは、main-axisの方向を垂直方向変えているということでしょう。しらんけど)

それに対して、widthは常に横方向に対しての幅を指定しています。

flex-basis: auto (初期値)時の話

https://drafts.csswg.org/css-flexbox-1/#flex-basis-property
~~~
For all values other than auto and content (defined above), flex-basis is resolved the same way as width in horizontal writing modes [CSS21], except that if a value would resolve to auto for width, it instead resolves to content for flex-basis. For example, percentage values of flex-basis are resolved against the flex item’s containing block (i.e. its flex container); and if that containing block’s size is indefinite, the used value for flex-basis is content. As another corollary, flex-basis determines the size of the content box, unless otherwise specified such as by box-sizing [CSS3UI].
~~~

flex-basis を指定しないまたは、autoの時は、widthの値が入ります。
さらに言えば、width: autoの時は、contentの幅が実質widthになるので、flex-basiscontentの幅になります。
初めはflex-basisでの指定された分、main axis方向に大きさを取ってくれます。
そして、flex-growを指定していると、親要素のmain axis方向に伸びれるだけ伸びてくれます。
ただし、min-widthまたはmax-width(←flex-direction:rowの時)が指定されている場合は、そちらが限界値として最優先されます。

こうして計算された値が、その要素の幅(flex-direction:columnなら高さ)になるはずです。
(ただし、ここが次の章で問題になります。)

今回問題になったやつ

See the Pen 不思議なwidth:0 by nonoakij (@nonoakij) on CodePen.

こちらで、.titleに当たっているwidth: 0を消してみると、緑色の帯が画面の横幅よりも伸びきってしまいます。
(文字が全て表示されてしまう。本当は、画面幅を超える場合は[...]でカットしたい。)

max-widthを指定してもうまくいかず、flex-basis: 0を指定してもうまくいかない。
しかしながら、なぜかwidth: 0をあてるとうまくいく、、、
上記記載の通り、widthに指定した値は、flex-basisを指定しない場合は、widthの値になるので、flex-basis: 0を指定しても同義なはずなのに、、、

考察とまとめ

こうなる原因として

  1. コンテンツの幅の計算タイミングがwidthflex-basisで異なるため
  2. 入れ子になった時、内側にあてたflex-growは、一番外側の要素の幅の限界まで伸びれてしまう。(実際、上の要素にmax-widthを指定すれば、それ以上は伸びなかった。

このいずれか、もしくは両方が関係してそう。

不明な点としては

  1. なぜか、flexの入れ子になっていなければ、この問題は起こらない ということ。

今回、アドベントカレンダーの期限までに完璧問題の究明はできなかったが、

  • どんなときにこの問題が起こるのか?
  • そもそも、flex-basiswidthの関係はなんぞや?
  • 原因はどこにありそうなのか?(growの方が問題あるかも?とか)

までは探ることができた。
引き続き、原因をしらべて、わかり次第追記したい。

次回は@ohteruさんの記事です!お楽しみに!

参考文献

https://drafts.csswg.org/css-flexbox-1/
https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes
https://developer.mozilla.org/ja/docs/Web/CSS/flex
https://developer.mozilla.org/ja/docs/Web/CSS/flex-grow
https://developer.mozilla.org/ja/docs/Web/CSS/flex-basis
https://gedd.ski/post/the-difference-between-width-and-flex-basis/
https://www.webcreatorbox.com/tech/css-flexbox-cheat-sheet

追記 2019/12/18
これが参考になる気がする
https://qiita.com/mpyw/items/dfc63c1fed5dfc5eda26

追記 2020/01/10
関係あるかも!?
flexにおけるmin-widthについて
min-widthは基本的にデフォルト0だが、flexの時はautoになる!?
https://drafts.csswg.org/css-flexbox-1/#min-size-auto
https://makandracards.com/makandra/66994-css-flex-and-min-width

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4