作者:紅塵煉心
https://juejin.im/post/5ea45801e51d4546d4399055
四年前端跪在CSS面試上,不可思議! CSS面試不是初級前端才會跪的嗎?在面試最後,面試官突然問了我最後一個問題。怎麼清除浮動。當然我很快給出最常用的方法。
.clearfix::after { content: ''; display: block; clear: both; visibility: hidden; height: 0;}本來我以為,面試官還會問,還有那些方法,我腦中已經構思了好幾種方法。沒想到,面試官竟然問我,這個方法清除浮動的原理。
原理!當時我就有點懵逼,這個方法很常見,也經常在用,但是就沒去理解過其原理。腦子在飛快的運轉。
首先::after是元素的偽元素,在元素後面;
content是偽元素的內容,為空,應該只是讓偽元素不顯示,而display:block;height:0保證偽元素高度為零不顯示,應該跟清除浮動沒多大關係。
另外visibility: hidden,是讓偽元素瀏覽器渲染但不顯示,也應該跟清除浮動沒多大關係。
那麼就剩下clear: both,我也不清楚它的含義,但是用排除法,這應該就是清除浮動的關鍵。
於是,我就含糊的回答,是clear: both這個屬性起了作用。但是面試官的表情告訴我,我的回答他很不滿意。
後面他又叫我,簡單講一下什麼是BFC,它有什麼作用。我只聽過KFC,哪裡聽過BFC,這下徹底懵逼了。平時在工作中大多數都是在寫JS代碼,很少去操作CSS。
雖然後來還是被錄取了,但是薪資下降了2K,達不到預期。只能很遺憾了。
回到家中,上網查一下資料,做個總結,分享一下。
CSS還是前端的基本功,不管你有多年工作經驗!!!別認為只有在初級前端面試中才會問CSS,警戒!!
一、清除浮動的原理沒錯,clear:both還真是清除浮動的關鍵,被我蒙對了。
clear是CSS中的定位屬性,規定元素的哪一側不允許其他浮動元素。那麼clear:both就是規定在左右兩側均不允許浮動元素。
clear屬性只能在塊級元素上其作用,這就是清除浮動樣式中display:block的作用。
另外visibility: hidden;height: 0;只要content的值為空。寫不寫都無所謂。
那麼為什麼要清除浮動,最常見的是因為外層容器高度坍塌,下面用一段代碼演示一下。
<style>.wrap { width: 200px; border: 1px solid #333;}.wrap:after { content: ''; display: block; clear: both;}.left { float: left; background: blue; height: 100px; width: 100px;}.right { float: left; background: red; height: 50px; width: 100px;}</style><body> <div class='wrap'> <div></div> <div></div> </div></body>為了顯示清楚一點,在.wrap:after 樣式中的content設置為content: 'after偽元素' ,此時如下圖所示。
隨後在.wrap:after 樣式中加上clear:both,表明after偽元素左右兩側均不允許浮動元素,沒辦法只好把after偽元素放在下面,此時如下圖所示。
順帶撐起了.wrap父元素的高度,這樣就相當清除了浮動了,解決了外層容器高度坍塌的問題。
那麼我們把.wrap:after 樣式中的content設置為content:' ',最後就如下圖所示。
二、BFC的概念和應用
1、BFC的概念BFC的全稱是 Block Formatting Contexts。
Formatting Contexts是頁面中的一塊渲染區域,它擁有一套渲染規則,決定其子元素將如何定位,以及和其它元素的關係和相互作用。說白了就是一個決定如何渲染元素的容器。
2、BFC的渲染規則那麼BFC就是一個決定如何渲染元素的容器。我們要了解就是它的渲染規則。
1、內部的塊級元素會在垂直方向,一個接一個地放置。
2、塊級元素垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰塊級元素的margin會發生重疊。
3、對於從左往右的格式化,每個元素(塊級元素與行內元素)的左邊緣,與包含塊的左邊緣相接觸,(對於從右往左的格式化則相反)。即使包含塊中的元素存在浮動也是如此,除非其中元素再生成一個BFC。
4、BFC的區域不會與浮動元素重疊。
5、BFC是一個隔離的獨立容器,容器裡面的子元素和外面的元素互不影響。
6、計算BFC容器的高度時,浮動元素也參與計算。
3、BFC的渲染規則詳解3.1 規則二以上渲染規則,第一點比較好理解。第二點我們用一個例子解釋一下。
<body> <div style="width:100px;height:100px;background:red;margin:20px;"></div> <div style="width:100px;height:100px;background:blue;margin:20px;"></div></body>按樣式代碼來看,紅塊和藍塊之間間距應該是40px。但實際上是20px。這就是BFC渲染規則的第二點。
因為BFC的觸發條件之一就是根元素,所以body就是一個BFC容器,紅塊和藍塊是同在body下的相鄰塊級元素,其margin會生重疊,所以紅塊和藍塊之間間距只有20px。
3.2 規則三第三點規則比較難理解我詳細解釋一下。首先要先理解包含塊的含義。
包含塊不是一個完整的box,一個完整的box包含margin包含塊,border包含塊,padding包含塊,content包含塊。
包含塊有可能是box的content包含塊,也可能是box的padding包含塊。這取決於被包含塊所包含的元素的position屬性。
例如,如果某個元素position屬性是absolute,包含塊就是由它的最近的position的值不是 static的父級元素的padding包含塊組成。
再例如,如果某個元素的position屬性是static或relative,包含塊就是由它的父級元素的content包含塊。
如果某個元素的position屬性是fixed,包含塊就是視口。
那麼。BFC中的元素應該與其自身的包含塊相接觸,而非與BFC相接觸,這個包含塊有可能是BFC中的一部分,也有可能和bfc無關。
正常元素都是從左往右的格式化,那麼對元素的position屬性是absolute,right為0,或者元素的float的屬性為right,那麼就是從右往左的格式化,元素的右邊緣和包含塊的右邊緣接觸。
元素H觸發生成BFC,其中有兩個元素A和元素B,元素A的float的屬性為left,那么元素A的左邊緣和元素H(也是元素A的包含塊)左邊緣接觸,如果元素B的float的屬性也為left,元素B的左邊緣不和元素H的左邊緣接觸,而是和元素A的右邊緣接觸。這種情況就可以用規則中的「即使包含塊中的元素存在浮動也是如此,除非其中元素再生成一個BFC」來解釋,元素的float的屬性不為none會觸發生成BFC,所以這種情況是不矛盾的。
3.3 規則四這點是BFC最重要的一點渲染規則,可以用這個規則解決很多布局的問題。
3.4 規則五這個規則,可以用來解決內部元素浮動,導致父級元素的高度坍塌問題。
4、BFC的觸發條件
三、BFC的應用
1、清除浮動在文章最初,提到用clear:both來清除浮動,我們也可以根據BFC的渲染規則第6點(計算BFC容器的高度時,浮動元素也參與計算)來清除浮動,解決高度坍塌的問題。
2、解決上下margin邊距問題<body> <div style="width:100px;height:100px;background:red;margin:20px;"></div> <div style="width:100px;height:100px;background:blue;margin:20px;"></div></body>我們利用BFC渲染規則第2點(屬於同一個BFC的兩個相鄰塊級元素的margin會發生重疊),那麼不屬於同一個BFC的兩個相鄰塊級元素的margin就不會發生重疊。
那麼我們在第二個div元素用一個div元素包裹起來,並用overflow:auto觸發其BFC。再看一下效果是不是不重疊了。
<body> <div style="width:100px;height:100px;background:red;margin:20px;"></div> <div style="overflow:auto"> <div style="width:100px;height:100px;background:blue;margin:20px;"></div> </div></body>3、實現自適應兩欄布局自適應兩欄布局,是一個主內容區域和一個側邊欄區域組成,兩個區域的寬度都可以隨窗口大小自適應。有很多種寫法可以實現。
這裡來實現一種利用BFC的渲染規則的寫法。
<style> .main{ background: red; height:500px; } .sider { float: left; width: 20%; height:300px; background: blue; }</stley><body> <div>我是側邊欄</div> <div>我是主體內容</div><body>首先我們根據規則1,要先把.sider div寫在.main div前面。這個.sider div才會浮動起來覆蓋在.main div上面。
再根據規則4(BFC的區域不會與浮動元素重疊),給.main加上overflow:auto;觸發.main div生成BFC。
四、IFC的概念和應用1、IFC的概念IFC的全稱是Inline Formatting Contexts,也就是「內聯格式化上下文」。
2、IFC的生成條件IFC的形成條件非常簡單,塊級元素中僅包含內聯級別元素,需要注意的是當IFC中有塊級元素插入時,會產生兩個匿名塊將父元素分割開來,產生兩個IFC。
3、IFC的渲染規則子元素水平方向橫向排列,並且垂直方向起點為元素頂部。
子元素只會計算橫向樣式空間,【padding、border、margin】,垂直方向樣式空間不會被計算,【padding、border、margin】。
在垂直方向上,子元素會以不同形式來對齊(vertical-align)
能把在一行上的框都完全包含進去的一個矩形區域,被稱為該行的行框(line box)。行框的寬度是由包含塊(containing box)和與其中的浮動來決定。
IFC中的「line box」一般左右邊貼緊其包含塊,但float元素會優先排列。
IFC中的「line box」高度由 CSS 行高計算規則來確定,同個IFC下的多個line box高度可能會不同。
當 inline-level boxes的總寬度少於包含它們的line box時,其水平渲染規則由 text-align 屬性值來決定。
當一個「inline box」超過父元素的寬度時,它會被分割成多個boxes,這些 boxes 分布在多個「line box」中。如果子元素未設置強制換行的情況下,「inline box」將不可被分割,將會溢出父元素。
4、IFC的應用
五、FFC的概念和應用
1、FFC的概念FFC的全稱是Flex formatting contexts,彈性盒模型。
2、FFC的生成條件父級元素設置display:flex或者`display:inline-flex
3、FFC的渲染規則`可以看阮一峰的Flex 布局教程:語法篇,講的非常詳細。
要注意一點。生成FFC後,其子元素的float、clear和vertical-align屬性將失效。
4、FFC的應用4.1、自動撐開頁面高度,底欄總是出現在頁面的底部<style>.wrap{ display:flex; padding:0; margin:0; min-height:100vh; flex-direction:column;}.main{ flex-grow:1;}</style><body class="wrap"> <header style="line-height:50px;background:red;color:#fff;text-align:center">頭部</header> <main class="main">內容</main> <footer style="line-height:50px;background:#eeeeee;color:#333;text-align:center">底欄</footer></body>4.2、經典的聖杯布局<style>.wrap { display: flex; padding: 0; margin: 0; min-height: 100vh; flex-direction: column;}header,footer { flex: 0 0 50px;}
.content { display: flex; flex: 1}
.main { flex: 1;}.nav,.ads{ flex: 0 0 100px; background:green;}.nav{ order:-1; background:yellow;}</style><body class="wrap"> <header style="line-height:50px;background:red;color:#fff;text-align:center">頭部</header> <div class="content"> <main class="main">內容區</main> <nav class="nav">側邊導航</nav> <aside class="ads">側邊欄</aside> </div> <footer style="line-height:50px;background:#eeeeee;color:#333;text-align:center">底欄</footer></body>