在彈性佈局中,一個
flex
子項的最終尺寸是基礎尺寸(或內容尺寸)、彈性增長或收縮、最大最小尺寸共同作用的結果。
最終尺寸計算的優先順序是:
最大最小尺寸限制 > 彈性增長或收縮 > 基礎尺寸
- 基礎尺寸由
flex-base
屬性或width
屬性,以及box-sizing
盒模型共同決定;- 內容尺寸最指最大內容寬度,當沒有設定基礎尺寸是會頂替基礎尺寸的角色;
- 彈性增長指的是
flex-grow
屬性,彈性收縮指的是flex-shrink
屬性;- 最大尺寸主要受
max-width
屬性限制;最小尺寸則比較複雜,受最小內容寬度、width
屬性和min-width
屬性共同影響。
很早之前就遇到過這個問題但沒有整理,當時處理完問題之後就沒有管了。昨天又遇到了同樣的問題,因為巢狀的層次很深折騰了有2個小時,所以還是需要記錄下來以免未來又忘了。
其實很簡單,容器使用 width:0;flex:1;
即可解決問題。
但是稍微有點沒有理解的是:為什麼設定寬度為 0
時,使用 flex-grow:1
可以使容器放大,但是設定寬度為 100%
時,使用 flex-shrink:1
並不會讓容器縮小。
先來看一下問題復現吧:
在正常內容的時候不會出現問題(可以點選 Demo 的 EDIT ON CODEPEN
最大化預覽正常情況),但當元素內部的文字內容增多時,或者視窗縮小時 flex
容器的寬度就會被內容撐開。
看起來是不是十分複雜?因為我巢狀了 2 層 flex
容器,最內部的容器 .list-item
因為內容太多被撐開了,並沒有如願按照剩餘空間縮小子元素 .text
的寬度,同時寬度變大的 .list-item
導致外部的 .container
和 .wrap
也被撐開了。
被撐開的 flex
容器比較多,不好說明,那麼看一下簡略版的復現 Demo ?
這個就很簡單明瞭了,因為 .text
的內容太多,致使 .container
容器被撐開了,並且 .container
的寬度變大使 .wrap
的寬度也增大了,並不是按照設想的 100vw
。同時文字標題超出省略的樣式也沒有應用到。
其實解決問題很簡單,容器使用 width:0;flex:1;
即可解決問題。
但是我疑惑的是,為什麼寬度設定為 0
,flex佈局可以使容器放大,設定為 100%
就不能實現縮小了。找了一圈也沒見原因,問了一下肉大,他說可能和內容寬度有關係,讓我看看張大佬的《CSS新世界》。
? 果然在 6.2.12
這一節找到了類似的例子,並在 6.3
這一節中找到了具體解釋。
那設定了 flex:1
屬性後,容器為什麼和預期表現不一致?(簡寫的 flex:1 具體簡寫了些什麼?)
因為設定了 flex-basis
屬性的元素的最小尺寸是最小內容的寬度(文字內容在所有換行點換行後的尺寸),而我設定了標題不換行導致最小尺寸比較大,最終尺寸大於 flex:1
給到的 flex-basis:0%
。(如果我們把標題設定會換行容器就不會被撐開了)。
具體解釋為:
flex-basis
屬性下的最小尺寸是由內容決定的,而width
屬性下的最小尺寸是由width
屬性的計算值決定的。
這裡出現的 “最小尺寸” 表示最終尺寸的最小值,所以在標題不換行的時候如果不設定 width
為 0
那麼,flex
容器的寬度就會被內容撐開。當設定 width:0
之後,最小尺寸就為設定的 width
值了,就可以被 flex-grow:1
放大。
ok,以上就是 flex
容器被內容撐開的全部內容了,有條件的小夥伴可以入手一本 《CSS新世界》 看看,裡邊的內容有很多講些CSS新特性的實用例子,確實可以節約不少時間。
文件
《CSS新世界》- 張鑫旭
flex - CSS(層疊樣式表) | MDN
flex-basis - CSS(層疊樣式表) | MDN