一道面试题目引发的思考
起因
多列布局是前端一個經典的反復被提及的面試題目,最典型的即兩列,左列定寬菜單欄,右列變寬為內容區域。
通常得到的答案無外乎左列浮動定寬,然后右列或浮動,或設置外邊距,或絕對定位等等。偶爾會有面試者給出設置右列overflow屬性的答案,心里就會有些驚喜,繼而會繼續追問,為什么這么設置就能實現效果,期待能有進一步驚喜,但基本大部分面試者都止步于這樣設置,并不清楚原因。非常少的面試者會提到這樣設置能夠觸發塊級格式化上下文(Block Formatting Conext, BFC),如果繼續追問觸發BFC的原因,幾乎沒有一個面試者能給出比較滿意的答案。
本文就是由這道面試題目引發的一些思考。針對設置overflow屬性這一方法,做進一步的探討。
overflow屬性
overflow屬性最常見的一個使用場景就是規定當內容溢出元素框時發生的事情??赡艿闹等缦?
- visible 默認值。元素內容不會被裁剪,元素框之外的內容仍然會呈現。
- hidden 元素內容會被裁剪,并且元素 框之外的內容是不可見的。
- scroll 元素內容會被裁剪,但是瀏覽器會顯示滾動條以便查看其余的內容。
- auto 瀏覽器自動處理元素內容的溢出,如果元素內容被裁剪,則瀏覽器會顯示滾動條以便查看其余的內容。
- inherit 規定應該從父元素繼承 overflow 屬性的值。
除此之外,也會經??吹酵ㄟ^overflow屬性實現的一些效果,比如清除浮動,以及上面提到的兩欄布局的實現。這些效果的實現,可能跟overflow屬性的本意相差甚遠,就像兩種不相關的事務被硬生生的牽扯到了一起。其實不然,CSS Spec規范文檔中還明確記錄著overflow屬性的另外一個重要作用。
overflow屬性跟布局的關系
The CSS2.1 spec mandates that overflow other than visible establish a new "block formatting context".
CSS2.1規范中已經明確提出,設置overflow屬性(非visible)能觸發塊級格式化上下文(Block Formatting Conext, BFC)。
BFC是個很大的話題,此處不展開,這里給出一個簡化不精確的解釋,BFC概念的引入,一定程度是為了特殊情況下布局計算的方便,元素觸發BFC之后,其作用就相當于一個根容器,其內部的子元素會跟外界完全隔離開,子元素布局以及尺寸相關的計算都會以該元素容器為基礎。
為什么overflow非visible值會觸發BFC?
首先,設置overflow屬性為visible的話,是一種默認情況,就相當于正常默認的布局,所有超出元素框的內容仍然會正常顯示,不會被裁剪,也不會出現滾動條。但對于其它幾種值的話(hidden, scroll, auto),元素的內容可能會被裁剪,此時,對于某些情況下可能出現的特殊布局處理就會出現爭議。
比如對于垂直方向緊貼著的兩個元素A和B,其中元素A中浮動的子元素可能會遮住元素B的部分文字區域,此時如果元素B的overflow屬性設置為visible,則內容會包裹在元素A浮動子元素的周圍,這種情況比較容易理解,如下圖。
overflow屬性設置為visible圖1 overflow屬性設置為visible
但當元素B的overflow屬性設置為非visible的值時,各版本規范的規定就會出現差異。
CSS2.0規范規定,設置非visible屬性值后,元素B的內容仍然包裹浮動元素,如圖2所示。
overflow屬性設置為novisible,CSS2.0規范中的處理圖2 overflow屬性設置為novisible,CSS2.0規范中的處理
此后如果元素B內容發生滾動,每次滾動行為,元素B中發生折疊的內容(圖3中元素B中文字內容滾動后發生變化)全部要重新計算重繪,實際上這將會帶來很大的性能問題,對滾動體驗也會造成比較大的影響。
overflow屬性設置為novisible,CSS2.0規范中發生滾動時的處理圖3 overflow屬性設置為novisible,CSS2.0規范中發生滾動時的處理
但這里存在進一步的疑問,即使按此規范的約定,元素B內容滾動時存在性能以及體驗問題,但是非visible屬性中的hidden值,難以理解,元素內容已經被裁剪掉了,為什么跟其它值auto, scroll歸為一類?這里面就存在一個誤區,overflow設置為hidden值并不代表內容不可滾動,此時瀏覽器只不過沒有提供可滾動的UI,被"裁剪"掉的內容可以通過JavaScript腳本來控制滾動,這也是腳本模擬滾動條的基礎。比如,可以通過JavaScript腳本設置元素的scrollTop實現圖4的效果,更友好的方式可以自定義一個滾動條。
overflow屬性設置為hidden,CSS2.0規范中發生滾動時的處理圖4 overflow屬性設置為hidden,CSS2.0規范中發生滾動時的處理
事實上各大瀏覽器廠商也都沒有遵照CSS2.0來實現這一部分規范。取而代之,實現的是CSS2.1中的規范內容,即當元素B的overflow屬性設置為非visible值時會觸發BFC,元素B會創建自己的塊級格式化上下文,并會被整體推向右側,如圖5所示。
overflow屬性設置為nonvisible,CSS2.1規范中的處理圖5 overflow屬性設置為nonvisible,CSS2.1規范中的處理
備注 上面各圖均來自于參考文獻3
收尾
事實上,一些常見的其它布局技巧也都是基于上述的原理點,比如overflow屬性非visible值可以用于清除浮動。如果一個面試者,能夠比較清楚地講出上面的各點,相信每個面試官心里面都會比較驚喜,上面只是自己的一些想法,可能會有些許的鉆牛角尖,但單從這種對細節的鉆研把控程度,候選人就一定不會太差,對候選人來說必然會有很大程度的加分。
上面只是針對兩列布局這道題目一種方案的單方面探討,這種方案有哪些優缺點等等都未提及,如果對每種方案都進行類似程度的拓展,將會發現這其中會涵蓋很多前端知識點,所以看似簡單的題目其實并不簡單。越發覺得前端領域的水很深,伙伴們一起來努力探索實踐吧!
參考文獻
- block formatting contexts
- The impact of 'overflow' values other than 'visible' on the block formatting context
- Re: CSS21 Why do overflow values other than 'visible' establish a new block formatting context?
- How does the CSS Block Formatting Context work?
Written by Hong
更多專業前端知識,請上 【猿2048】www.mk2048.com
總結
以上是生活随笔為你收集整理的一道面试题目引发的思考的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 笔记:隐式转换规则
- 下一篇: 服务器端如何开启GZIP压缩功能