前端人員不要只知道KFC,你應該了解 BFC、IFC、GFC 和 FFC


前言

說起KFC,大家都知道是肯德基🍟,但面試官問你什么是BFC、IFC、GFC和FFC的時候,你是否能夠像回答KFC是肯德基時的迅速,又或者說后面這些你根本就沒聽說過,作為一名前端開發工程師,以上這些FC(Forrmatting Context)你都得知道,而且必須得做到像肯德基這樣印象深刻。下面我將會帶大家一起揭開這些FC的真面目,如果你已經了解的請獎勵自己一頓肯德基~(注意文明用語,這里別用語氣詞😂)

FC的全稱是:Formatting Contexts,譯作格式化上下文,是W3C CSS2.1規范中的一個概念。它是頁面中的一塊渲染區域,並且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關系和相互作用。

CSS2.1中只有BFC和IFC,CSS3中才有GFC和FFC。

如果這篇文章有幫助到你,❤️關注+點贊❤️鼓勵一下作者,文章公眾號首發,關注 前端南玖 第一時間獲取最新的文章~

前置概念

在學習各種FC之前,我們先來了解幾個基本概念:

Box(CSS布局基本單位)

簡單來講,我們看到的所有頁面都是由一個個Box組合而成的,元素的類型和display屬性決定了Box的類型。

  • block-level Box: 當元素的 CSS 屬性 displayblock, list-item table 時,它是塊級元素 block-level 。塊級元素(比如<p>)視覺上呈現為塊,豎直排列。
    每個塊級元素至少生成一個塊級盒(block-level Box)參與 BFC ,稱為主要塊級盒(principal block-level box)。一些元素,比如<li>,生成額外的盒來放置項目符號,不過多數元素只生成一個主要塊級盒。
  • Inline-level Box: 當元素的 CSS 屬性 display 的計算值為 inline, inline-block inline-table 時,稱它為行內級元素。視覺上它將內容與其它行內級元素排列為多行。典型的如段落內容,有文本或圖片,都是行內級元素。行內級元素生成行內級盒(inline-level boxes),參與行內格式化上下文 IFC 。
  • flex container: 當元素的 CSS 屬性 display 的計算值為 flexinline-flex ,稱它為彈性容器display:flex這個值會導致一個元素生成一個塊級(block-level)彈性容器框。display:inline-flex這個值會導致一個元素生成一個行內級(inline-level)彈性容器框。
  • grid container:當元素的 CSS 屬性 display 的計算值為 grid inline-grid,稱它為柵格容器

塊容器盒(block container box)

只包含其它塊級盒,或生成一個行內格式化上下文(inline formatting context),只包含行內盒的叫做塊容器盒子

也就是說,塊容器盒要么只包含行內級盒,要么只包含塊級盒。

塊級盒(block-level Box)是描述元素跟它的父元素與兄弟元素之間的表現。

塊容器盒(block container box)描述元素跟它的后代之間的影響。

塊盒(BLock Boxes)

同時是塊容器盒的塊級盒稱為塊盒(block boxes)

行盒(Line boxes)

行盒由行內格式化上下文(inline formatting context)產生的盒,用於表示一行。在塊盒里面,行盒從塊盒一邊排版到另一邊。 當有浮動時, 行盒從左浮動的最右邊排版到右浮動的最左邊。

OK,了解完上面這些概念,我們再來看我們本篇文章的重點內容(終於要揭開各種FC的廬山真面目了,期待~)

BFC(Block Formatting Contexts)塊級格式化上下文

什么是BFC?

BFC 全稱:Block Formatting Context, 名為 塊級格式化上下文

W3C官方解釋為:BFC它決定了元素如何對其內容進行定位,以及與其它元素的關系和相互作用,當涉及到可視化布局時,Block Formatting Context提供了一個環境,HTML在這個環境中按照一定的規則進行布局。

如何觸發BFC?

  • 根元素或其它包含它的元素

  • 浮動 float: left/right/inherit

  • 絕對定位元素 position: absolute/fixed

  • 行內塊 display: inline-block

  • 表格單元格 display: table-cell

  • 表格標題 display: table-caption

  • 溢出元素 overflow: hidden/scroll/auto/inherit

  • 彈性盒子 display: flex/inline-flex

BFC布局規則

  • 內部的Box會在垂直方向,一個接一個地放置。

  • Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊。

  • 每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,否則相反)。即使存在浮動也是如此。

  • BFC的區域不會與float box重疊。

  • BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。反之也如此。

  • 計算BFC的高度時,浮動元素也參與計算

BFC應用場景

解決塊級元素垂直方向margin重疊

我們來看下面這種情況:

<style>
  .box{
    width:180px;
    height:180px;
    background:rosybrown;
    color:#fff;
    margin: 60px auto;
  }
</style>
<body>
    <div class="box">nanjiu</div>
    <div class="box">南玖</div>
</body>

按我們習慣性思維,上面這個box的margin-bottom60px,下面這個box的margin-top也是60px,那他們垂直的間距按道理來說應該是120px才對。(可事實並非如此,我們可以來具體看一下)

bfc1.png
從圖中我們可以看到,兩個box的垂直間距只有60px,並不是120px!

這種情況下的margin邊距為兩者的最大值,而不是兩者相加,那么我們可以使用BFC來解決這種margin塌陷的問題。

<style>
  .box{
    width:180px;
    height:180px;
    background:rosybrown;
    color:#fff;
    margin: 60px auto;
  }
  .outer_box{
    overflow: hidden;
  }
</style>
<body>
    <div class="outer_box">
        <div class="box">nanjiu</div>
    </div>
    <div class="box">南玖</div>
</body>

bfc2.png
由上面可以看到,我們通過給第一個box外面再包裹一層容器,並觸發它形成BFC,此時的兩個box就不屬於同一個BFC了,它們的布局互不干擾,所以這時候他們的垂直間距就是兩者間距相加了。

解決高度塌陷問題

我們再來看這種情況,內部box使用float脫離了普通文檔流,導致外層容器沒辦法撐起高度,使得背景顏色沒有顯示出來。

<style>
  .box{
    float:left;
    width:180px;
    height:180px;
    background:rosybrown;
    color:#fff;
    margin: 60px;
  }
  .outer_box{
    background:lightblue;
  }
</style>
<body>
    <div class="outer_box">
        <div class="box">nanjiu</div>
        <div class="box">南玖</div>
    </div>
</body>

bfc3.png
從這張圖,我們可以看到此時的外層容器的高度為0,導致背景顏色沒有渲染出來,這種情況我們同樣可以使用BFC來解決,可以直接為外層容器觸發BFC,我們來看看效果:

<style>
  .box{
    float:left;
    width:180px;
    height:180px;
    background:rosybrown;
    color:#fff;
    margin: 60px;
  }
.outer_box{
  display:inline-block;
  background:lightblue;
}
</style>
<body>
    <div class="outer_box">
        <div class="box">nanjiu</div>
        <div class="box">南玖</div>
    </div>
</body>

bfc4.png

清除浮動

在早期前端頁面大多喜歡用浮動來布局,但浮動元素脫離普通文檔流,會覆蓋旁邊內容:

<style>
.aside {
  float: left;
  width:180px;
  height: 300px;
  background:lightpink;
  }
  .container{
    width:500px;
    height:400px;
    background:mediumturquoise;
  }
</style>
<body>
    <div class="outer_box">
        <div class="aside">nanjiu</div>
        <div class="container">南玖</div>
    </div>
</body>

bfc5.png
我們可以通過觸發后面這個元素形成BFC,從而來清楚浮動元素對其布局造成的影響

<style>
.aside {
  float: left;
  width:180px;
  height: 300px;
  background:lightpink;
  }
  .container{
    width:500px;
    height:400px;
    background:mediumturquoise;
    overflow: hidden;
  }
</style>
<body>
    <div class="outer_box">
        <div class="aside">nanjiu</div>
        <div class="container">南玖</div>
    </div>
</body>

bfc6.png

IFC(Inline Formatting Contexts)行內級格式化上下文

什么是IFC?

IFC全稱:Inline Formatting Context,名為行級格式化上下文

如何觸發IFC?

  • 塊級元素中僅包含內聯級別元素

形成條件非常簡單,需要注意的是當IFC中有塊級元素插入時,會產生兩個匿名塊將父元素分割開來,產生兩個IFC。

IFC布局規則

  • 在一個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 boxes的總寬度少於包含它們的line box時,其水平渲染規則由 text-align 屬性值來決定。
  • 當一個inline box超過父元素的寬度時,它會被分割成多個boxes,這些boxes分布在多個line box中。如果子元素未設置強制換行的情況下,inline box將不可被分割,將會溢出父元素。

IFC應用場景

元素水平居中

當一個塊要在環境中水平居中時,設置其為inline-block則會在外層產生IFC,通過text-align則可以使其水平居中。

<style>
	/* IFC */
  .text_container{
    width: 650px;
    border: 3px solid salmon;
    margin-top:60px;
    text-align: center;
  }
  strong,span{
    /* border:1px solid cornflowerblue; */
    margin: 20px;
    background-color: cornflowerblue;
    color:#fff;
  }
</style>
<body>
    <div class="text_container">
        <strong>眾里尋他千百度,南玖需要你關注</strong>
        <span>驀然回首,那人卻在,南玖前端交流群</span>
    </div>
</body>

ifc1.png

多行文本水平垂直居中

創建一個IFC,然后設置其vertical-align:middle,其他行內元素則可以在此父元素下垂直居中。

<style>
.text_container{
  text-align: center;
  line-height: 300px;
  width: 100%;
  height: 300px;
  background-color: turquoise;
  font-size: 0;
  }
  p{
    line-height: normal;
    display: inline-block;
    vertical-align: middle;
    background-color: coral;
    font-size: 18px;
    padding: 10px;
    width: 360px;
    color: #fff;
  }
</style>
<body>
  <div class="text_container">
    <p>
      東風夜放花千樹,更吹落,星如雨。寶馬雕車香滿路。鳳簫聲動,玉壺光轉,一夜魚龍舞。蛾兒雪柳黃金縷,笑語盈盈暗香去。
      <strong>眾里尋他千百度,驀然回首,那人卻在,燈火闌珊處。</strong>
    </p>
  </div>
</body>

ifc2.png

GFC(Grid Formatting Contexts)柵格格式化上下文

什么是GFC?

GFC全稱:Grids Formatting Contexts,名為網格格式上下文

簡介:
CSS3引入的一種新的布局模型——Grids網格布局,目前暫未推廣使用,使用頻率較低,簡單了解即可。
Grid 布局與 Flex 布局有一定的相似性,都可以指定容器內部多個項目的位置。但是,它們也存在重大區別。
Flex 布局是軸線布局,只能指定"項目"針對軸線的位置,可以看作是一維布局。Grid 布局則是將容器划分成"行"和"列",產生單元格,然后指定"項目所在"的單元格,可以看作是二維布局。Grid 布局遠比 Flex 布局強大。

如何觸發GFC?

當為一個元素設置display值為grid或者inline-grid的時候,此元素將會獲得一個獨立的渲染區域。

GFC布局規則

通過在網格容器(grid container)上定義網格定義行(grid definition rows)網格定義列(grid definition columns)屬性各在網格項目(grid item)上定義網格行(grid row)和網格列(grid columns)為每一個網格項目(grid item)定義位置和空間(具體可以在MDN上查看)

GFC應用場景

任意魔方布局

這個布局使用用GFC可以輕松實現自由拼接效果,換成其他方法,一般會使用相對/絕對定位,或者flex來實現自由拼接效果,復雜程度將會提升好幾個等級。

<style>
.magic{
  display: grid;
  grid-gap: 2px;
  width:300px;
  height:300px;
  }
  .magic div{
    border: 1px solid coral;
  }
  .m_1{
    grid-column-start: 1;
    grid-column-end: 3;
  }
  .m_3{
    grid-column-start: 2;
    grid-column-end: 4;
    grid-row-start: 2;
    grid-row-end: 3;
  }
</style>
<body>
  <div class="magic">
    <div class="m_1">1</div>
    <div class="m_2">2</div>
    <div class="m_3">3</div>
    <div class="m_4">4</div>
    <div class="m_5">5</div>
    <div class="m_6">6</div>
    <div class="m_7">7</div>
  </div>
</body>

gfc1.png

FFC(Flex Formatting Contexts)彈性格式化上下文

什么是FFC?

FFC全稱:Flex Formatting Contexts,名為彈性格式上下文

簡介:
CSS3引入了一種新的布局模型——flex布局。
flex是flexible box的縮寫,一般稱之為彈性盒模型。和CSS3其他屬性不一樣,flexbox並不是一個屬性,而是一個模塊,包括多個CSS3屬性。flex布局提供一種更加有效的方式來進行容器內的項目布局,以適應各種類型的顯示設備和各種尺寸的屏幕,使用Flex box布局實際上就是聲明創建了FFC(自適應格式上下文)

如何觸發FFC?

display 的值為 flexinline-flex 時,將生成彈性容器(Flex Containers), 一個彈性容器為其內容建立了一個新的彈性格式化上下文環境(FFC)

FFC布局規則

  • 設置為 flex 的容器被渲染為一個塊級元素
  • 設置為 inline-flex 的容器被渲染為一個行內元素
  • 彈性容器中的每一個子元素都是一個彈性項目。彈性項目可以是任意數量的。彈性容器外和彈性項目內的一切元素都不受影響。簡單地說,Flexbox 定義了彈性容器內彈性項目該如何布局

⚠️注意:FFC布局中,float、clear、vertical-align屬性不會生效。

Flex 布局是軸線布局,只能指定"項目"針對軸線的位置,可以看作是一維布局。Grid 布局則是將容器划分成"行"和"列",產生單元格,然后指定"項目所在"的單元格,可以看作是二維布局。Grid 布局遠比 Flex 布局強大。

FFC應用場景

這里只介紹它對於其它布局所相對來說更方便的特點,其實flex布局現在是非常普遍的,很多前端人員都喜歡用flex來寫頁面布局,操作方便且靈活,兼容性好。

自動撐開剩余高度/寬度

看一個經典兩欄布局:左邊為側邊導航欄,右邊為內容區域,用我們之前的常規布局,可能就需要使用到csscalc方法來動態計算剩余填充寬度了,但如果使用flex布局的話,只需要一個屬性就能解決這個問題:

calc動態計算方法:

<style>
.outer_box {
	width:100%;
} 
.aside {
  float: left;
  width:180px;
  height: 300px;
  background:lightpink;
}
.container{
  width:calc(100% - 180px);
  height:400px;
  background:mediumturquoise;
  overflow: hidden;
 }
</style>
<body>
		<div class="outer_box">
        <div class="aside">nanjiu</div>
        <div class="container">南玖</div>
    </div>
</body>

ffc.gif
使用FFC:

<style>
.outer_box {
  display:flex;
	width:100%;
} 
.aside {
  float: left;
  width:180px;
  height: 300px;
  background:lightpink;
}
.container{
  flex: 1;
  height:400px;
  background:mediumturquoise;
  overflow: hidden;
 }
</style>
<body>
		<div class="outer_box">
        <div class="aside">nanjiu</div>
        <div class="container">南玖</div>
    </div>
</body>

ffc2.gif

總結

一般來說,FFC能做的事情,通過GFC都能搞定,反過來GFC能做的事通過FFC也能實現。
通常彈性布局使用FFC,二維網格布局使用GFC,所有的FFC與GFC也是一個BFC,在遵循自己的規范的情況下,向下兼容BFC規范。

現在所有的FC都介紹完了,了解清楚的去獎勵自己一頓KFC吧😄~

推薦閱讀

原文首發地址點這里,歡迎大家關注公眾號 「前端南玖」

我是南玖,我們下期見!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM