大家都不看的總集篇: 從零開始的大前端築基之旅(深刻淺出,持續更新~)
以爲不錯就順手點個贊吧~css
劃重點: 本文全部示例均爲手打html示例,能夠直接選中示例在控制檯調試,方便驗證各類想法。手敲不易,若是你以爲示例調試方便,那我在此求個贊~html
外邊距重疊就是 margin-collapse
。相鄰的兩個盒子(多是兄弟關係也多是祖先關係)的外邊距能夠結合成一個單獨的外邊距。 這種合併外邊距的方式被稱爲摺疊,結合而成的外邊距稱爲摺疊外邊距。前端
摺疊結果遵循下列計算原則:react
有些人看到這裏可能會想:啊,我作列表的時候遇到過這種狀況,折騰了我半天呢。webpack
另外一些人可能會想:這是什麼玩意,我怎麼沒遇到過?這難道不是css的bug麼?css3
咱們先來講說什麼狀況下不會產生外邊距重疊web
等等,先不要列舉了,這些條件怎麼看着那麼眼熟呢?嗯。。。這不就是生成BFC的條件麼。。。。typescript
BFC(Block formatting context)直譯爲"塊級格式化上下文"。它是一個獨立的渲染區域,只有Block-level box參與, 它規定了內部的Block-level Box如何佈局,而且與這個區域外部絕不相干。segmentfault
咱們常說的文檔流其實分爲定位流、浮動流、普通流三種。而普通流其實就是指BFC中的FC。FC(Formatting Context),直譯過來是格式化上下文,它是頁面中的一塊渲染區域,有一套渲染規則,決定了其子元素如何佈局,以及和其餘元素之間的關係和做用。babel
先介紹下Box、Formatting Context的概念。
Box:css佈局的基本單位
Box 是 CSS 佈局的對象和基本單位, 直觀點來講,就是一個頁面是由不少個 Box 組成的。元素的類型和 display 屬性,決定了這個 Box 的類型。 不一樣類型的 Box, 會參與不一樣的 Formatting Context(一個決定如何渲染文檔的容器),所以Box內的元素會以不一樣的方式渲染。
block-level box:display
屬性爲 block, list-item, table 的元素,會生成 block-level box。而且參與 block fomatting context;inline-level box:display
屬性爲 inline, inline-block, inline-table 的元素,會生成 inline-level box。而且參與 inline formatting context;run-in box
: css3 中才有, 這兒先不講了。Formatting Context
Formatting context
是 W3C CSS2.1 規範中的一個概念。它是頁面中的一塊渲染區域,而且有一套渲染規則,它決定了其子元素將如何定位,以及和其餘元素的關係和相互做用。最多見的 Formatting context
有 Block fomatting context
(簡稱BFC)和 Inline formatting context
(簡稱IFC)。
具備 BFC 特性的元素能夠看做是隔離了的獨立容器,容器裏面的元素不會在佈局上影響到外面的元素,而且 BFC 具備普通容器所沒有的一些特性。
內部的Box會在垂直方向,一個接一個地放置。
Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊。
每一個盒子(塊盒與行盒)的margin box的左邊,與包含塊border box的左邊相接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此。即BFC中子元素不會超出他的包含塊。
BFC的區域不會與float box重疊。
BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素。反之也如此。
計算BFC的高度時,浮動元素也參與計算。
display: table
也能夠生成BFC的緣由在於Table會默認生成一個匿名的table-cell,是這個匿名的table-cell生成了BFC。BFC是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面元素,反之亦然。咱們能夠利用BFC的這個特性來作不少事。
<div class="container">
<div class="inner"></div>
<div class="inner"></div>
</div>
複製代碼
.container{
display: inline-block;
border: 1px solid grey;
}
.inner{
width: 20px;
height: 20px;
margin: 20px;
border: 1px solid grey;
background: lightblue;
}
複製代碼
從效果上看,由於兩個 div 元素都處於同一個 BFC 容器下 (這裏經過設置container
爲 display: inline-block
) 因此第一個 div 的下邊距和第二個 div 的上邊距發生了重疊,因此兩個盒子之間距離只有 20px,而不是 40px。
首先這不是 CSS 的 bug,咱們能夠理解爲一種規範,若是想要避免外邊距的重疊,能夠將其放在不一樣的 BFC 容器中。
<div class="container">
<div class="inner"></div>
<div class="container1">
<div class="inner"></div>
</div>
</div>
複製代碼
.container{
display: inline-block;
border: 1px solid grey;
}
.container1{
display: inline-block;
}
.inner{
width: 20px;
height: 40px;
margin: 40px;
border: 1px solid grey;
background: orange;
overflow: hidden;
}
複製代碼
這裏,將第二個div
放進container1
中,經過設置container
爲 display: inline-block
使其產生BFC,這樣,兩個inner
就在不一樣的BFC下,邊距就不會重疊。兩個盒子之間距離是 40px。
ps:此樣例使用html編寫,可直接點擊示例在控制檯調試,試試取消container1
的style以後的效果吧
浮動的元素會脫離普通文檔流,來看下下面一個例子
<div class="container">
<div class="inner"></div>
</div>
複製代碼
.container{
border: 1px solid grey;
}
.inner{
width: 20px;
height: 20px;
margin: 20px;
background: orange;
float: left;
}
複製代碼
栗子,包括下面的橫線
因爲容器內元素浮動,脫離了文檔流,因此容器只剩下 2px 的邊距高度。若是使觸發容器的 BFC,那麼容器將會包裹着浮動元素。
經過overflow: hidden
使container
生成BFC
.container{
border: 1px solid grey;
overflow: hidden;
}
複製代碼
本例也能夠直接點擊調試哦~
你真的清楚浮動效果麼?告訴你個浮動的隱藏效果,做爲交換,你給我點個贊,咋樣
解釋這個做用以前,我先來解釋一下什麼是浮動
什麼是浮動
元素加了浮動後,會脫離文檔流,提高了半層層級,向着指定方向移動,直到遇到父元素的邊界或另外一個浮動元素中止
什麼是層級
若是將整個元素看作一層,則下半層是元素自己(背景樣式等),上半層是元素中的內容
舉例
<div class="container">
<div class="box1">box1</div>
<div class="box2">box2</div>
<div class="box3">box3</div>
</div>
複製代碼
.container{
width: 40px;
border: 1px solid black;
}
.container div{
width: 100%;
height: 30px;
}
.box1 {
background: yellow;
}
.box2 {
background: orange;
}
.box3 {
background: pink;
}
複製代碼
三個盒子都沒有浮動時
當給box2添加float:left時,三個盒子的排列變成
此時因爲box2浮動脫離了文檔流,box3上移,被box2遮擋了。但此時box3盒子裏的文字box3並無上移!!!
小知識
position:absolute
和float
會隱式地改變display
類型,除display:none
外,只要設置了position:absolute
或float
,都會讓元素以display:inline-block
的方式顯示,能夠設置長寬浮動效果講完了,咱們來看看元素被浮動元素覆蓋的例子
<div class="container">
<div class="left">我是一個左浮動的元素</div>
<div class="right">我是一個沒有設置浮動,
也沒有觸發 BFC 的元素, 個人一部分被覆蓋了</div>
</div>
複製代碼
.left{
width: 100px;
height: 50px;
background: orange;
float: left;
}
.right{
width: 200px;
height: 200px;
background: lightblue;
}
複製代碼
第二個元素有部分被浮動元素所覆蓋,(可是文本信息不會被浮動元素所覆蓋,緣由在上面浮動例子解釋過) 若是想避免元素被覆蓋,可觸第二個元素的 BFC 特性,在第二個元素中加入 overflow: hidden,就會變成:
這個方法能夠用來實現兩列自適應佈局,經過設置container
的寬度,去掉right
的寬度便可。這時候左邊的寬度固定,右邊的內容自適應寬度。
Ps: 建議在控制檯調試一下本示例
ps:我通常使用display: flex
,而後左側寬度固定,右側設置flex: 1
,這個方法垂直方向也可使用,我經常使用來設置滾動列表的高度,這個方法也能夠實現動態寬度的佈局
例子以下:
<div class="container">
<div class="left">左側元素,定寬</div>
<div class="right">右側元素,動態填充剩餘空間</div>
</div>
複製代碼
.container{
width: 400px;
display: flex;
border: 1px solid grey;
}
.left{
width: 100px;
height: 50px;
background: orange;
}
.right{
height: 200px;
flex: 1;
background: lightblue;
}
複製代碼
你能夠在控制檯調整一下container
的寬度,右側元素會自動填充
講完了BFC及其做用,除了最直觀的,同一個 BFC 下外邊距會發生摺疊,咱們來看下其餘邊距重疊的示例
栗子以下:
<div class="container">
<div class="title">
此部分是能更容易看出讓下面的塊的margin-top。
</div>
<div class = "content">
<div class="inner">
子元素
margin-top:20px;
</div>
<h2>父元素</h2>
沒有設置margin-top
</div>
</div>
複製代碼
.container{
width: 400px;
border: 1px solid grey;
}
.title{
height:50px;
background: #eee;
}
.content{
height:200px;
background: #88f;
}
.inner{
height:100px;
margin-top:20px;
background: #0ff;
width:200px;
}
複製代碼
父元素和子元素margin-top發生了重疊,最終結果至關於父元素設置了20px的margin-top。
能夠設置 overflow:hidden
來解決這個問題。你能夠選中示例在控制檯本身嘗試一下其餘解決方案。
<div class="container">
<div class="inner"></div>
</div>
複製代碼
.container{
width: 200px;
border: 1px solid grey;
}
.inner{
margin-top:20px;
margin-bottom: 20px;
}
複製代碼
這個框的高度只有20px,稍微改動下inner元素,好比加個文字,或者加個邊框,都會破壞這種現象,歡迎本身打開控制檯嘗試一下各類解決方案。
好了,外邊距重疊、BFC、及浮動的講解到此結束。有任何想法和意見歡迎在評論中指出。若是你收穫了新知識,請點個贊告訴我~
本文收納於: 從零開始的大前端築基之旅(深刻淺出,持續更新~)
推薦閱讀:
帶你擼個屬於本身的react項目|webpack+babel+typescript+eslint
沒搭過項目的新人必定不容錯過,帶你解鎖快捷開發小技巧
三言兩語帶你理解「閉包」| 附使用場景
很簡單就能解釋清的東西爲何要多費口舌呢?
朝花夕拾,從新介紹繼承與原型鏈
有圖有真相的講解
迴流(reflow)與重繪(repaint),KFC與MC
每次這兩個都會被同時說起,關係就好像KFC邊上必定會有MC同樣親密的讓人摸不到頭腦。
viewport和1px | 工具人: 這是1px,設計師: 不,這不是
設計我不行,但吵架我在行啊
可食用的「css佈局乾貨」,純Html示例,可調試 | 水平、垂直、多列
可觀看,可調試,可帶走,僅此一家,別無分店
前端必須掌握的「CSS層疊上下文」講解 | 純手工示例,包教包會
妹子與貓,你要哪一個?
參考文檔: