Flex布局中一個不為人知的特性
關(guān)于本文要說的這個特性,我之前也不清楚,還是遇到問題之后,閱讀規(guī)范才知道的,故事是下面這樣的:
某日被告知有一個bug:在網(wǎng)頁寬度較小時,發(fā)現(xiàn) Flex 容器被子元素?fù)未髮?dǎo)致UI顯示異常的問題,如下:

這是什么鬼...我期待它不管什么時候都能像下面這樣顯示(不撐破父容器):

我開始一頓操作猛如虎,各種審查元素樣式,恕我愚鈍,并沒有看出什么問題,看起來似乎都很正確的樣子....
當(dāng)然,瀏覽器是不會騙我的,雖然,不知道哪里出了問題,但是這并不影響我修復(fù)這個問題。我試了試,發(fā)現(xiàn)加個 flex 容器加個 overflow:hidden 屬性之后,完美解決問題。然后又試了試,發(fā)現(xiàn)加 min-width: 0 也可以解決這個問題。
bug 改好了,但是不知道為什么加個 overflow:hidden 或者 min-width: 0 就好了。

想來我非常普通的CSS水平可能無法解開這一難題,于是我開始思考朋友圈哪位大佬對CSS頗有研究,于是我就寫了個最簡的Demo,然后微信去請教了下大佬,大佬跟我說:原理說起來可就復(fù)雜了,然后分享我一篇文章鏈接。我看完之后,發(fā)現(xiàn)對我的問題并沒有一個非常好的解釋,于是又繼續(xù)厚著臉皮問了,大佬說這塊可能他也沒有覆蓋到。
好嘛,畢竟是周五,也不好一直騷擾大佬,于是,我就繼續(xù)自己尋找答案。其實寫最簡Demo的時候,我發(fā)現(xiàn)了一個小小問題,那就是:其實這個問題出現(xiàn)在 Flex 嵌套之中,如果不是嵌套的話,那么 Flex 容器并不會被 Flex 的項目撐破??梢源吝@個查看最簡Demo:https://codepen.io/yvettelau/pen/OJWMdoM?editors=1100

如果我們刪除掉 div class=main 那一層,那么表現(xiàn)良好,即每個 item 都按照預(yù)期縮小了。

然鵝,還是不知道原因吖,搜索引擎找了一番也沒找到什么有說服力的答案,于是,我決定研究一下 flex 的規(guī)范(https://www.w3.org/TR/css-flexbox-1/#min-size-auto),看到如下一段話:

通過閱讀標(biāo)準(zhǔn),可以發(fā)現(xiàn):
在非滾動容器中,主軸方向Flex Item 的最小尺寸是基于內(nèi)容的最小尺寸,此時 min-width 的值是 auto。對于滾動容器,min-width 的值是 0(默認(rèn)討論水平布局)
讀到這里,我意識到這個問題跟Flex嵌套應(yīng)該沒什么關(guān)系,不嵌套應(yīng)該也一樣存在這個問題,于是我又新寫了個demo,可以戳這個查看:https://codepen.io/yvettelau/pen/poRgYPK?editors=1100

當(dāng) item 的內(nèi)容 child 寬度是250px時,此時也不能按照預(yù)期縮小??赡苓@個時候,第一反應(yīng)是給 item 加 flex-shrink,然而并木有用。—— 當(dāng) min-width是 auto 時,其最小尺寸是基于內(nèi)容的,加 flex-shrink 是沒有作用的。
這個時候就乖乖按照規(guī)范教的操作吧,例如,我們給 item 設(shè)置 min-width:0 ,這個時候,item 會按照預(yù)期縮小,平分500px的大小。

另外,規(guī)范也說明了在滾動容器中,min-width 也是0,所以,給 item 增加 overflow: auto 或者 overflow: hidden 也一樣可以達到目的。
現(xiàn)在,我們再回過頭來看文章最開始的問題??雌饋硎?Flex 嵌套導(dǎo)致的問題,其實是因為嵌套在里面的 div ,它不僅僅是 Flex 容器,同時它也是一個 Flex Item。因此,我們可以給它加上 overflow: hidden 或者是 min-width: 0 來阻止它撐破父容器。
最后的最后,吐槽一句,CSS真是太復(fù)雜了...
參考鏈接:
https://www.w3.org/TR/css-flexbox-1/#transferred-size-suggestion 還有一個忘記保存鏈接的stackflow
