CSS 盒模型、BFC、IFC、GFC、FFC

基本慨念

內(nèi)容區(qū)域(content)是包含元素真實(shí)內(nèi)容的區(qū)域。它通常包含背景、顏色或者圖片等,位于內(nèi)容邊界的內(nèi)部,它的大小為內(nèi)容寬度或 content-box 寬及內(nèi)容高度或 content-box 高。

如果 box-sizing 為默認(rèn)值,width、min-width、max-width、height、min-height、max-height控制內(nèi)容大小。

內(nèi)邊距區(qū)域(padding)延伸到包圍 padding 的邊框。如果內(nèi)容區(qū)域設(shè)置了背景、顏色或者圖片,這些樣式將會延伸到 padding 上。它位于內(nèi)邊距邊界內(nèi)部,它的大小為 padding-box 寬與 padding-box 高。

內(nèi)邊距與內(nèi)容邊界之間的空間可以由 padding-top、padding-right、padding-bottom、padding-left 和簡寫屬性 padding 控制。

邊框區(qū)域(border)是包含邊框的區(qū)域,擴(kuò)展了內(nèi)邊距區(qū)域。它位于邊框邊界內(nèi)部,大小為 border-box 寬和 border-box 高。

由 border-width 及簡寫屬性 border 控制。

外邊距區(qū)域(margin)用空白區(qū)域擴(kuò)展邊框區(qū)域,以分開相鄰元素。它的大小為 margin-box 的高寬。

外邊距區(qū)域大小由 margin-top、margin-right、margin-bottom、margin-left ?及簡寫屬性 margin 控制。

注意:對于非替換行內(nèi)元素來說,盡管內(nèi)容周圍存在內(nèi)邊距與邊框,但其占用空間(行高)由 line-height 屬性決定。

標(biāo)準(zhǔn)盒模型:width = content

IE 盒模型:width = content + 2 * padding + 2 * border

CSS 如何設(shè)置這兩種模型

用到了 CSS3 的屬性 box-sizing

/* 標(biāo)準(zhǔn)模型 */?

box-sizing: content-box;?

/*IE模型*/

?box-sizing: border-box;

JS 獲取寬高

通過 JS 獲取盒模型對應(yīng)的寬和高,有一下幾種方式,以下用 dom 來表示獲取的 HTML節(jié)點(diǎn):

1. dom.style.width/height

? ? 這種方式只能取到 dom 元素內(nèi)聯(lián)樣式所設(shè)置的寬高,也就是說如果該節(jié)點(diǎn)的樣式是在 style 標(biāo)簽中或外聯(lián)的 CSS 文件中設(shè)置的話,通過這種方式是獲取不到 dom 的寬高的。

2. dom.currentStyle.width/height

? ? 這種方式獲取的是在頁面渲染完成后的結(jié)果,就是說不管是哪種方式設(shè)置的樣式,都能獲取到。到這種方式只有 IE 支持

3. window.getComputedStyle(dom).width/height

? ? 這種方式的原理和 2 一樣,這個可以兼容更多的瀏覽器,通用性更好。

4. dom.getBoundingClientRect().width/height

? ? 這種方式是根據(jù)元素在視窗中的絕對位置來獲取寬高的。

5. dom.offsetWidth/offsetHeight

? ? 包括高度(寬度)、內(nèi)邊距和邊框,不包括外邊距。最常用,兼容性最好。

邊距重疊與BFC

邊距重疊

邊距重疊是指兩個或多個盒子(可能相鄰也可能嵌套)的相鄰邊界重合在一起而形成一個單一邊界。

兩個或多個塊級盒子的垂直相鄰邊界會重合,它們的邊界寬度是相鄰邊界寬度的最大值。注意水平邊界是不會重合的。

邊距重疊例子

父子元素的邊界重疊

<style type="text/css">

????.parent {

????????background: #E7A1C5;

????????height: 200px; width: 200px;

????}

????.child {

????????background: #C8CDF5;

????????height: 100px;

????????width: 100px;

????????margin-top: 10px;

????}

</style>

<section class="parent">

????<article class="child"></article>

</section>

期待的效果:

實(shí)際效果:

這里父元素的高度不是110px,而是100px,在這里發(fā)生了高度坍塌。原因是如果塊元素的 margin-top 與它的第一個子元素的 margin-top 之間沒有 border、padding等來分隔,或者塊元素的 margin-bottom與它最后一個子元素的 margin-bottom 之間沒有 border、padding、height、min-height、max-height 分隔,那么外邊距會塌陷。子元素多余的外邊距會被父元素的外邊距截?cái)唷?/p>

兄弟元素的邊界重疊

<style>

????#margin {

????????background: #E7A1C5;

????????overflow: hidden;

????????width: 300px;

????}

????#margin>p {

????????background: #C8CDF5;

????????margin: 20px auto 30px;

????}

</style>

<section id="margin">

????<p>1</p>

????<p>2</p>

????<p>3</p>

</section>

可以看到 1 和 2 之間、2 和 3 之間的間距不是 50px ,發(fā)生了邊距重疊是取它們之間的最大值 30px.

空元素的邊界重疊

假設(shè)有一個空元素,它有外邊距,但是沒有邊框或填充。在這種情況下,上外邊距與下外邊距就碰到了一起,它們會發(fā)生合并:

BFC 原理

解決上述問題的其中一個辦法就是創(chuàng)建 BFC。BFC 的全稱為 Block Formatting Content,即塊級格式化上下文。一個 BFC 有如下特性:

1. 處于同一個 BFC 中的元素相互影響,可能會發(fā)生 margin collapse
2. BFC 在頁面上是一個獨(dú)立的容器,容器里面的子元素不會影響到外面的元素,反之亦然
3. 計(jì)算 BFC 的高度時,考慮 BFC 所包含的所有元素,包括浮動元素也參與計(jì)算
4. 浮動盒的區(qū)域不會疊加到 BFC 上

創(chuàng)建 BFC

創(chuàng)建 BFC 的方法如下:

1. 浮動( float 的值不為 none )
2. 絕對定位元素( position 的值為 absolute 或 fixed )
3. 行內(nèi)塊( display 為 inline-block )
4. 表格單元( display 為 table、table-cell、table-caption 等 HTML 表格相關(guān)的屬性 )
5. 彈性盒( display 為 flex 或 inline-flex )
6. overflow 不為 visible

BFC 使用場景

1. 防止垂直 margin 重疊

父子元素的邊界重疊得解決方案:

在父元素上加上 overflow: hidden; 使其成為 BFC。

.parent {

????background: #E7A1C5;

????overflow: hidden;

}

兄弟元素的邊界重疊,在第二個子元素創(chuàng)建一個 BFC 上下文:

<section id="margin">

????<p>1</p>

????<div style="overflow:hidden;">

????????<p>2</p>

????</div>

????<p>3</p>

</section>

2. 清除內(nèi)部浮動

<style>

????#float {

????????background: #FEC68B;

????}

????#float .float {

????????float: left;

????}

</style>

<section id="float">

????<div class="float">我是浮動元素</div>

</section>

父元素 #float 的高度為 0,解決方案為:為父元素創(chuàng)建 BFC,這樣浮動子元素的高度也會參與到父元素的高度計(jì)算:

#float {

????background: #FEC68B;

????overflow: hidden; /*這里也可以用float:left*/

}

3. 自適應(yīng)兩欄布局

<section id="layout">

????<style>

????????#layout {

????????????background: red;

????????}

????????#layout .left {

????????????float: left;

????????????width: 100px;

????????????height: 100px;

????????????background: pink;

????????}

? ? ? ? #layout .right {

????????????height: 110px;

????????????background: #ccc;

????????}

</style>

<!--左邊寬度固定,右邊自適應(yīng)-->

<div class="left">左</div>

<div class="right">右</div>

</section>

在這里設(shè)置右邊的高度高于左邊,可以看到左邊超出的部分跑到右邊去了,這是由于浮動框不在文檔的普通流中,所以文檔的普通流中的塊框表現(xiàn)得就像浮動框不存在一樣導(dǎo)致的。

解決方案為:給右側(cè)元素創(chuàng)建一個 BFC,原理就是 BFC 不會與 float 元素發(fā)生重疊。

#layout .right {

????height: 110px;

????background: #ccc;

????overflow: auto;

}

IFC 原理

全稱 Inline Formatting Contexts,也就是"內(nèi)聯(lián)格式化上下文"。

創(chuàng)建 IFC?

塊級元素中僅包含內(nèi)聯(lián)級別元素。
當(dāng) IFC 中有塊級元素插入時,會產(chǎn)生兩個匿名塊將父元素分割開來,產(chǎn)生兩個 IFC。

IFC 的布局規(guī)則:

1. 子元素水平方向排列,并且垂直方向起點(diǎn)為元素頂部
2. 子元素只會計(jì)算水平方向元素空間(margin padding border),不會計(jì)算垂直方向
3. 在垂直方向上,子元素會以不同形式來對齊(vertical-align)
4. 能把一行上的框全部包含進(jìn)去的一個矩形區(qū)域,被稱為該行的行框(line box)。行框的寬度由包含塊(containing box)和與其中的浮動元素來決定
5. IFC 中的 "line box" 一般緊貼其包含塊,但 float 元素會優(yōu)先排列
6. IFC 中的 "line box" 高度由 CSS 行高計(jì)算規(guī)則來確定,同個 IFC 下的多個?"line box" 高度可能會不同
7. 當(dāng)內(nèi)聯(lián)元素的總寬度小于包含它們的??"line box" 時,其水平渲染規(guī)則由 "text-align" 屬性值來決定
8. 當(dāng)一個??"line box" 超過父元素的寬度時,它會被分割成多個 box,這些 box 分布在多個 "line box" 中。如果子元素未設(shè)置強(qiáng)制換行的情況下,"inline box" 將不可被分割,將會溢出父元素

IFC 使用場景:

1. 水平居中:當(dāng)一個塊要在環(huán)境中水平居中時,設(shè)置其為inline-block則會在外層產(chǎn)生IFC,通過text-align則可以使其水平居中。
2. 垂直居中:創(chuàng)建一個IFC,用其中一個元素?fù)伍_父元素的高度,然后設(shè)置其vertical-align:middle,其他行內(nèi)元素則可以在此父元素下垂直居中。

GFC 原理

GFC(GridLayout Formatting Contexts)直譯為"網(wǎng)格布局格式化上下文",當(dāng)為一個元素設(shè)置display值為grid的時候,此元素將會獲得一個獨(dú)立的渲染區(qū)域,我們可以通過在網(wǎng)格容器(grid container)上定義網(wǎng)格定義行(grid definition rows)和網(wǎng)格定義列(grid definition columns)屬性各在網(wǎng)格項(xiàng)目(grid item)上定義網(wǎng)格行(grid row)和網(wǎng)格列(grid columns)為每一個網(wǎng)格項(xiàng)目(grid item)定義位置和空間。?

和 table 的區(qū)別:同樣是一個二維表格,gridLayout 會以更加豐富的屬性來控制行列、控制對齊以及更精細(xì)的控制語義

FFC 原理

FFC(Flex Formatting Contexts)直譯為"自適應(yīng)格式化上下文",display 值為flex 或者 inline-flex 的元素將會生成自適應(yīng)容器(flex container)。

Flex Box 由伸縮容器和伸縮項(xiàng)目組成。通過設(shè)置元素的 display 屬性為 flex 或 inline-flex 可以得到一個伸縮容器。設(shè)置為 flex 的容器被渲染為一個塊級元素,而設(shè)置為 inline-flex 的容器則渲染為一個行內(nèi)元素。

伸縮容器中的每一個子元素都是一個伸縮項(xiàng)目。伸縮項(xiàng)目可以是任意數(shù)量的。伸縮容器外和伸縮項(xiàng)目內(nèi)的一切元素都不受影響。簡單地說,F(xiàn)lexbox 定義了伸縮容器內(nèi)伸縮項(xiàng)目該如何布局。

參考:盒子模型 - CSS:層疊樣式表 | MDN

? ??????????深入理解CSS盒模型 - 程序猿的程 - 博客園

? ??????????邊距重疊與BFC - 個人文章 - SegmentFault 思否

? ??????????CSS之IFC - 前端大寶劍 - SegmentFault 思否

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 食貨星球上有這么一個讓人又愛又恨的團(tuán)體,每天潛伏在食貨好奇官群里“為非作歹”。美食素材庫像個黑洞,一言不合就發(fā)吃,...
    食貨君閱讀 281評論 0 0
  • 不要把我對你的容忍 當(dāng)作你不要臉的資本
    感謝經(jīng)歷258閱讀 161評論 0 0
  • 今天我們?nèi)ケ本?,坐了火車和地鐵。我們?nèi)チ颂彀查T廣場,天安門廣場很多人挨挨擠擠的,廣場中央有一個花壇,上面有各...
    梔子花開1234閱讀 281評論 0 0
  • 1 寫作群里拋出一個問題,平時氣氛沉默的群里炸開了鍋,也許是因?yàn)檫@個問題,可以引起大家的共鳴。寶寶們七嘴八舌的回復(fù)...
    蘇青梵閱讀 548評論 4 3
  • 2017.12.10 周日 高暢 孔子回到魯國后,自六十八歲到七十三歲卒,共生活了五年。在這五年中,他跨越了自...
    暢_759c閱讀 341評論 0 0

友情鏈接更多精彩內(nèi)容