總括: 對於盒子模型,BFC,IFC和外邊距合併等概念和問題的總結css
原文地址:從CSS盒子模型提及html
知乎專欄:前端進擊者前端
博主博客地址:Damonare的我的博客git
爲學之道,莫先於窮理;窮理之要,必先於讀書。github
CSS盒子模型是CSS基礎中的基礎,我的以前對於這塊的理解有誤差?,因爲涉及知識點比較多因此寫一篇總結備忘。
以前打算的是兩週一次更新博文的,可是時間用在了刷題上,作了不少leetcode上算法數據結構的題記錄在github,但其實也有在更新啦~只不過是對以前的一些博文進行糾正:)?算法
最近秋招在即,壓力倍增,前幾天把博客導入頁的在讀大三本科生
改成了在讀大四本科生
,不由心生感慨,時光荏苒。轉眼間個人這個小窩居然已經快一年了。當初創建這個站點也是想找個說話的地方,有的人可能就是不喜歡說,只喜歡寫(好比我),然而自從實習後確實提不起精神來寫了,一是沒精力,二是對於遇到的一些坑不想單獨寫一篇博客記錄。這裏仍是想保持一份純淨,就是以總結和理解難點爲主調 其它的通常會託管在github庫裏記錄一下。閒話很少說,說說今天的主角?♀️瀏覽器
CSS盒子模型想來都不陌生,但仍是想先介紹一下,以保證文章的完整性。?數據結構
CSS盒子模型:async
在一個文檔中,每個元素都被抽象成一個盒子,每個盒子又包括四部分(從內到外):內容(content),內填充(padding),邊框(border),外邊距(margin)。見上圖,這是從二維的角度分析,來張三維立體圖:?ide
此圖很形象的解釋了CSS盒子的構成:
content box:立體盒子的核心
padding box:內邊距區域padding area 延伸到包圍padding的邊框。若是內容區域content area設置了背景、顏色或者圖片,這些樣式將會延伸到padding上(固然咱們能夠經過background-clip設置做用區域)
border box:由border和4條border edge組成。若border寬度設置爲0,則border edge與padding edage重疊;
margin box:由margin和4條margin edge組成。若margin寬度設置爲0,則margin edge與border edage重疊。
?看起來很複雜的樣子...
拿PS圖層的概念更好理解這塊,最上面的就是content box往下一次是padding box,border box,margin box。
那麼盒子模型通常分爲兩種:
所謂IE盒子模型,就是以前IE瀏覽器實現的一種怪異的盒子模型,怎麼怪異呢?當咱們這樣設置的時候:
div { width: 100px; height: 100px; }
理論上咱們想要設置的就是content box的寬高嘛,可是IE在解析的時候會按照這個規則解析:
width = content-width + padding-width + border-width
height = content-height + padding-height + border-height
這就致使了這種尷尬的境地:下面無內容的話直接戳這裏?
<script async src="https://jsfiddle.net/Damonare...
標準就比較符合常人的思惟了,設置的width,height就是content的width和height
規則就是:
width = content-width
height = content-height
實例以下:無內容戳這?
<script async src="https://jsfiddle.net/Damonare...
可能秉着寬大爲懷的準則,CSS3加了個box-sizing屬性,變相認可了這兩種盒子都對(好吧,可能一我的有一我的的見解吧),不過box-sizing默認屬性就是content-box,即標準盒子模式,IE盒子模型呢,是屬性border-box。剛剛查MDN發現還有一個屬性padding-box(width=content-width+padding-width),不過並無瀏覽器實現它(真可憐),並沒有卵用?
剛剛說的是以塊級元素爲例說的,那麼行內元素呢?好吧,其實你知道,行內盒是無法設置width和height的,那麼以前我就有了這樣的思惟定勢:行內盒沒有padding,margin,而後發現,哦!行內盒是有padding-left,padding-right,margin-left,margin-right的!WOC!,而後又發現,行內盒是實際上身懷八甲...?
<script async src="https://jsfiddle.net/Damonare...
行內盒子的高由font-size決定的;
行內盒子的寬等於其子行級盒子的外寬度(margin+border+padding+content width)之和。
是有padding-top和padding-bottom,margin-left,margin-bottom的但並不佔據空間…這就符合盒子模型了嘛,既都是盒子,天然應該是同樣的。行內盒的margin-top, margin-bottom不佔空間,由此聯想到了另外一個問題——?
所謂外邊距合併呢,就是margin合併嘛,看下MDN的定義:
塊的頂部外邊距和底部外邊距有時被組合(摺疊)爲單個外邊距,其大小是組合到其中的最大外邊距,這種行爲稱爲外邊距合併。
?注意只是上下,沒有說左右。並且是針對塊級元素說的。
外邊距合併有這幾種狀況:
//HTML <div class="up">我在上面</div> <div class="down">我在下面</div> //CSS .up { width: 100px; height: 100px; border: 1px solid blue; margin: 100px; } .down { width: 100px; height: 100px; border: 1px solid red; margin: 100px; }
咱們感性上以爲上下兩個元素應該是相差200px距離,然而並非。
若是塊級父元素中,不存在上邊框、上內補、inline content、清除浮動這四條屬性(對於上邊框和上內補,也能夠說,當上邊距及上內補寬度爲0時),那麼這個塊級元素和其第一個子元素的上邊距就能夠說」捱到了一塊兒「。此時這個塊級父元素和其第一個子元素就會發生 上外邊距合併 現象,換句話說,此時這個父元素對外展示出來的外邊距將直接變成這個父元素和其第一個子元素的margin-top的較大者。?
//HTML <div class="parent"> <div class="child">我是兒子</div> </div> //CSS .parent { width: 100px; height: 200px; background: red; margin-left: 100px; } .child { width: 50px; height: 50px; margin-top: 100px; border: 1px solid blue; }
上面代碼感性上可能會以爲,父元素沒有上邊距,然而並非。
MDN給了三種狀況,但第三種空塊元素,我以爲能夠包含在這兩種以內,就沒舉?
那麼這種外邊距合併的狀況咋解決呢?看下一個概念...
?定義:
一個塊格式化上下文(block formatting context) 是Web頁面的可視化CSS渲染的一部分。它是塊盒子的佈局發生,浮動互相交互的區域。
那麼觸發BFC的狀況有哪些呢?
看MDN:
?一個塊格式化上下文由如下之一建立:
根元素或其它包含它的元素
浮動 (元素的
float
不是 none
)
絕對定位的元素 (元素具備 position
爲 absolute
或 fixed
)
內聯塊 inline-blocks (元素具備 display
: inline-block
)
表格單元格 (元素具備 display
: table-cell,HTML表格單元格默認屬性
)
表格標題 (元素具備 display
: table-caption
, HTML表格標題默認屬性)
塊元素具備overflow
,且值不是 visible
display
: flow-root
注意,根元素就建立了一個BFC
那麼BFC又有一下特性:
內部塊級盒子垂直方向排列
盒子垂直距離由margin決定,同一個BFC的盒子外邊距會合並
BFC就是一個隔離的容器,內部子元素不會影響到外部元素
每一個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此。
BFC的區域不會與float box疊加。
好,上面外邊距合併的兩種狀況,利用BFC如何解決呢?下面沒內容的話請戳這裏?
<script async src="https://jsfiddle.net/Damonare...
關於第四五條特性,請看上面的示例。
BFC用途:
清除浮動;
解決外邊距合併;
佈局;
關於這塊有好多個概念...首先是塊級元素和塊級盒子:每一個塊級元素至少生成一個塊級盒,稱爲主要塊級盒。一些元素,好比li,生成額外的盒來放置項目符號,不過多數元素只生成一個主要塊級盒。
主要塊級盒將包含後代元素生成的盒以及生成的內容。它也是可使用(定位方案 positioning scheme)的盒。
塊容器盒(block container box) 只包含其它塊級盒,或生成一個行內格式化上下文(inline formatting context)
注意塊級盒與塊容器盒概念不一樣。 前者描述元素跟它的父元素與兄弟元素之間的表現,後者描述元素跟它的後代之間的影響。
同時是塊容器盒的塊級盒稱爲塊盒(block boxes)。(注意塊盒和塊級盒並非全等)
還有一個特殊的塊盒——匿名塊盒
<div>Some inline text <p>followed by a paragraph</p> followed by more inline text.</div> //將建立兩個匿名塊盒,一個包含 <p> 前面的文本 (Some inline text), 一個包含 <p> 後面的文本(followed by more inline text),
塊級元素觸發BFC,行內元素會觸發啥麼❓
IFC 只有在一個塊級元素中僅包含內聯級別元素時纔會生成。
當元素的 CSS 屬性 display的計算值爲 inline
, inline-block
或 inline-table
時,稱它爲行內級元素。視覺上它將內容與其它行內級元素排列爲多行。典型的如段落內容,有文本(能夠有多種格式譬如着重),或圖片,都是行內級元素。
行內級元素生成行內級盒(inline-level boxes),參與行內格式化上下文(inline formatting context)。同時參與生成行內格式化上下文的行內級盒稱爲行內盒(Inline boxes)。全部display:inline 的非替換元素生成的盒是行內盒。而不參與生成行內格式化上下文的行內級盒稱爲原子行內級盒(*atomic inline-level boxes)。這些盒由可替換行內元素,或 display 值爲 inline-block
或 inline-table
的元素生成,不能拆分紅多個盒。
另外CSS3還新增了兩種格式上下文:GFC(Grid Formatting Contexts)柵格格式化上下文和FFC(Flex Formatting Contexts)Flex格式化上下文,即分別在元素display爲grid和flex、 inline-flex 時觸發
分清了這些盒子的概念,具體怎麼排列呢?如下來自MDN:
在常規流中,盒一個接着一個排列。在塊級格式化上下文裏面, 它們豎着排列;在行內格式化上下文裏面, 它們橫着排列。 當 position爲 static
或 relative
,而且 float 爲 none
時會觸發常規流。
對於浮動定位方案(float positioning scheme), 盒稱爲浮動盒(floating boxes)。它位於當前行的開頭或末尾。這致使常規流環繞在它的周邊,除非設置 clear 屬性。
要使用浮動定位方案,元素 CSS 屬性position 爲 static
或 relative
,而後 float
不爲 none
。若是 float
設爲 left
, 浮動由行盒的開頭開始定位。若是設爲 right
, 浮動定位在行盒的末尾。
對於絕對定位方案, 盒從常規流中被移除,不影響常規流的佈局。 它的定位相對於它的包含塊,相關CSS屬性:top, bottom, left及right 。
若是元素的屬性position爲 absolute
或 fixed, 它是絕對定位元素。
固定定位元素(fixed positioned element)也是絕對定位元素,它的包含塊是視口。當頁面滾動時它固定在屏幕上,由於視口沒有移動。
以上。