真是一個小例子引發(fā)的“命案”呀谜悟,原本只是在想為什么一個容器內(nèi)的塊元素幾個塊元素會發(fā)生外邊距(margin collapse)商叹,然后找啊找啊找估蹄,就找到了BFC(Block Formating context)次绘。>
真是很福氣自己,被自己感動哭了
首先刽酱,我會從 BFC是什么喳逛? 如何形成BFC? BFC的應(yīng)用 這三個方面入手棵里。
1 BFC 是什么润文?
BFC 是web頁面中盒模型布局中的CSS渲染模式,定位機制屬于普通流模式殿怜。
一個塊格式化上下文(block formatting context) 是Web頁面的可視化CSS渲染出的一部分转唉。它是塊級盒布局出現(xiàn)的區(qū)域,也是浮動層元素進行交互的區(qū)域稳捆。
(我們都知道,CSS中的定位機制有三種形式:1 普通流模式 2 浮動 3 定位麦轰。)BFC其實就是一個獨立的布局環(huán)境乔夯,其中的元素不受外界影響。> 我知道你現(xiàn)在看到這里肯定還不知道我在說什么款侵,說實話末荐,我一開始看其他文章也是這樣的,還是繼續(xù)往下看新锈,回頭再來理解概念吧甲脏。
2 創(chuàng)建BFC
一個元素要創(chuàng)建BFC,需要滿足以下幾個條件妹笆,才能形成BFC块请。
- float的值不是none.
- position 的值不是static或者relative。
- display的值是inline-block,table-cell,flex,table-caption或者inline-flex拳缠。(其實這個除了flex其他我好像都沒用過)
- overflow的值不是visible含末。
所以辅甥,只要滿足以上四個條件就可以創(chuàng)建BFC了,但是,等等,我們要創(chuàng)建BFC干嘛梭姓?首先應(yīng)該知道BFC的實際用處,我們才會在實際應(yīng)用中使用它。那么接下來就是盔憨,BFC的作用,我會用好多個例子來證明一下讯沈。
3 BFC的特性 (人家雖然好用郁岩,也是有缺點的,例如外邊距合并問題)
- 1 BFC內(nèi)的元素會導(dǎo)致 外邊距合并芙盘。 (在BFC當(dāng)中驯用,盒子都是從它的包含塊一個一個垂直放置的,兩個相鄰盒子的垂直間距取決于margin屬性儒老,所以兩個相鄰塊會發(fā)生垂直外邊距塌陷蝴乔。)
- 2 BFC中每一個盒子的左外側(cè)緊貼包含塊的左側(cè),(從右到左的格式里驮樊,則為盒子右側(cè)緊貼包含快右側(cè))甚至有浮動也是如此薇正。(浮動的元素是脫離文檔流的,所以其他元素為將其當(dāng)作不存在)囚衔。
- 3 計算BFC的高度時挖腰,浮動元素也會計算進內(nèi)。(所以练湿,你懂的猴仑,我們可以給包含有浮動元素的父元素,設(shè)置成BFC肥哎,就可以 解決浮動元素導(dǎo)致的父元素坍塌的問題辽俗。)
- 4 BFC元素不會與浮動元素重合。 !!!理解這個很重要!!!!
BFC元素不會與浮動元素重合篡诽。 我需要說明一點就是崖飘,這是一個清除浮動的很好的方式啊啊啊。
1 當(dāng)一個容器中有一個左浮動元素和一個BFC元素的時候杈女,BFC的寬度如果可以在剩余空間存放的話朱浴,就會顯示在浮動元素所在行的剩余空間內(nèi)。
2 當(dāng) BFC 的寬度大于容器剩余寬度時达椰,最新版本的瀏覽中只有firefox會在同一行顯示翰蠢,其它瀏覽器均換行。
是不是有點暈了啰劲,這個時候最好不要放棄躏筏,繼續(xù)往下看,重頭戲還在后頭呈枉,知道了這些基礎(chǔ)的東西之后趁尼,我們需要知道一些關(guān)于BFC的實踐應(yīng)用和基本原理埃碱。
4 BFC 實踐及其原理。
1 自適應(yīng)兩欄布局 (原理參照:BFC的第4條屬性酥泞。)
先看下面的代碼:
CSS部分:
<style>
.container {
width:400px;
margin:200px;
}
.leftpart {
float: left;
width:100px;
height:200px;
background: plum;
color: white;
}
.rightpart {
height:300px;
background: pink;
color: white;
}
</style>
html部分:
<body>
<div class="container">
<div class="leftpart">我是左邊的那一塊</div>
<div class="rightpart">我是右邊的那一塊砚殿,聽說我會環(huán)繞在左邊的浮動元素上,我也是沒辦法啊芝囤,因為浮動元素是脫離文檔流的似炎,我誰將它當(dāng)作不存在,然后占據(jù)他所在的空間呢
也只有將我設(shè)置成BFC的形式悯姊,我才不會這樣呢羡藐?不信你試一試</div>
</div>
</body>
左邊的設(shè)置了左浮動,因為浮動元素脫離文檔流悯许,所以結(jié)果會是下面這個樣子仆嗦。
很顯然,這不是我們想要的結(jié)果先壕,前面提到了BFC的特性中瘩扼,有一條提到,BFC不會與浮動元素觸碰垃僚,那么我們是不是可以給右邊的元素設(shè)置成BFC集绰。
那么其實,就是在.rightpart
設(shè)置多一個樣式屬性就可以了谆棺。
.rightpart {overflow:auto;} // 前面提到了如何形成一個BFC栽燕,可以設(shè)置overflow不為visible。
那么改淑,我們來看看效果圖纫谅。
這樣,我們右邊的那一塊溅固,沒有設(shè)置寬度,會自動根據(jù)容易的寬度還有浮動元素的寬度兰珍,自適應(yīng)的分配寬度給右邊那一塊侍郭。這樣也給我們的自適應(yīng)布局提供了思路呀。
對了掠河,如果希望左右兩欄有間距亮元,你可以這么做。
你會發(fā)現(xiàn)唠摹,你給右邊那一塊設(shè)置了margin-left
之后爆捞,并沒有你理想中那樣。假設(shè)我添加了
.rightpart {margin-left:20px;} // 只是設(shè)置了20
你會發(fā)現(xiàn)勾拉。這兩欄看上去還是沒有間距的煮甥。其實從下圖可以發(fā)現(xiàn)盗温,不是margin不起作用。
我的理解是成肘,margin-left
確實是起作用了卖局,但是它其實還是將浮動元素看做是不占據(jù)文檔流的,只是BFC元素的盒模型中border內(nèi)的不再去搶浮動元素的空間双霍,但是margin
還是會搶占浮動元素的空間的砚偶。所以,要想看到兩欄有間距洒闸,需要設(shè)置的margin-left
要大于leftpart
的寬度染坯。
(當(dāng)然,這并不是明智之舉丘逸,要是你不知道leftpart的寬度单鹿,豈不是悲劇了)
試一下:
.rightpart {margin-left:120px;} // 只是設(shè)置了120
其實,不用那么麻煩鸣个。我們只需要給 leftpart
設(shè)置margin-right 就可以了羞反。
上面其實也只是想詳細的去理解這個過程。
.leftpart {margin-right:20px;}
不知道你有沒有發(fā)現(xiàn)囤萤,如果我們之前不設(shè)置BFC的話昼窗,也就是不給rightpart
設(shè)置成BFC的話,直接就是設(shè)置rightpart的margin-left大于左浮動元素的寬度涛舍,也可以達到兩欄布局的效果澄惊,但是,~~~那樣很麻煩啊富雅,如果不知道寬度怎么辦掸驱。
所以,兩欄布局的最佳實踐應(yīng)該是: margin-left + BFC模式没佑。
(當(dāng)然毕贼,用flex布局會更加方便,但是這也不失為一種好方法呀蛤奢。)
2 解決含有浮動元素的父元素塌陷問題
首先鬼癣,這個問題的存在原因是因為浮動元素是脫離文檔流的,所以包裹浮動元素的父元素其實并不能被撐開啤贩,所以就會導(dǎo)致下面的結(jié)果待秃,看一下圖。
上例所示圖的代碼如下:
// 很明顯痹屹,兩個子模塊的定位都是浮動形式章郁,而父元素發(fā)生了坍塌。
html部分:
<body>
<div class="mainPart">
<div class="testpart"></div>
<div class="testpart"></div>
</div>
</body>
CSS部分:
.mainPart {
background: royalblue;
border:1px solid olivedrab;
width:500px;
}
.testpart {
float: left;
width:200px;
height:200px;
background: plum;
margin:10px;
}
那么志衍?怎么解決這個問題暖庄。
當(dāng)然聊替。你可以向通常的清除浮動的方法一樣,在父元素內(nèi)部添加一個空元素雄驹,設(shè)置clear:both;
可以達到清除浮動的效果佃牛。
那如何通過設(shè)置一個BFC去清除浮動呢?
前面第3點中提到:
計算BFC的高度時医舆,浮動元素也會計算進內(nèi)俘侠。
所以,可以將父元素設(shè)置成BFC蔬将,就可以達到清除浮動爷速,清除高度坍塌問題。
// 給父元素添加以下樣式
.mainPart {
overflow:auto;
}
那么霞怀,效果如下圖:
所以惫东,可以通過給父元素設(shè)置成BFC來清除浮動。
3 BFC內(nèi)部元素外邊距塌陷問題解決毙石。
前面提到的BFC的原理特性中廉沮,有一個就是外邊距合并問題。(這又是一個大boss,我最近也在看這方面的資料徐矩,后續(xù)會補上詳細的筆記的)
BFC垂直方向上的距離由margin值所決定滞时,同一個BFC內(nèi)的兩個相鄰元素的margin值會重疊。
什么意思捏~~~~
先看下圖:
其實兩個粉色的子元素滤灯,已經(jīng)設(shè)置了margin值為20了坪稽。按照道理來說的話,上下兩塊之間的距離應(yīng)該是40的鳞骤。但是這里只是20.也就是外邊距合并最后是取比較大的那一個窒百。
(其實我想了一下,我覺得這個外邊距合并用在這里挺好的呀豫尽,有時候如果我們想實現(xiàn)下面這樣一個效果篙梢,其實我覺得外邊距合并的存在反倒是好的呢)
只需要給每一個子元素設(shè)置margin為20即可。(當(dāng)然美旧,父元素和第一個子元素以及最后一個子元素也會發(fā)生合并問題渤滞, ~~啊啊啊,我后面會貼上一文章來解釋的陈症,~~)
針對這種子元素發(fā)生外邊距合并的處理方法。
我們可以將子元素重新設(shè)置成一個BFC就可以了震糖。
你想想录肯,一開始,在同一個BFC下的子元素之所以會發(fā)生垂直外邊距合并(對了吊说,外邊距合并只發(fā)生在垂直方向论咏,水平方向不會的优炬。),是因為父元素的高度是由子元素決定的厅贪,所以高度也會發(fā)生外邊距合并了蠢护。
解決方法就是,用一個元素給第二個子元素包在一個新的BFC內(nèi)养涮。
html部分:
<div class="father">
<div class="son"></div>
<div style="overflow: auto"> // 這里設(shè)置了父元素葵硕,同時設(shè)置overflow:auto。
<div class="son" ></div>
</div>
</div>
CSS部分:
.father {
width:100px;
height:200px;
background: red;
/*margin:20px;*/
}
.son {
width:30px;
height:90px;
margin: 20px;
background: plum;
}
這樣的話贯吓,結(jié)果就如下所示了:
后記: 我理解的BFC其實就是CSS中的一個渲染機制懈凹,BFC就相當(dāng)于一個盒子,內(nèi)部的元素與外界的元素互不干擾悄谐。它不會影響外部的布局介评,外部的布局也不會影響到它。你想一下爬舰,為什么設(shè)置了BFC之后就可以清除浮動们陆,我的理解就是,設(shè)置了BFC之后的元素就是一個獨立的個體情屹,內(nèi)部有浮動元素也不會再影響外部的元素了坪仇。那為什么設(shè)置了BFC之后,不會發(fā)生對周圍元素的環(huán)繞現(xiàn)象屁商,也是同一個道理烟很。所以,這么去想一想蜡镶,其實BFC我們就一直有在使用雾袱,只是自己不知道而已。