理解 CSS 佈局和 BFC

阿里雲最近在作活動,低至2折,有興趣能夠看看:
https://promotion.aliyun.com/...

爲了保證的可讀性,本文采用意譯而非直譯。css

CSS佈局中有一些概念,一旦你理解了它們,就能真正提升你的 CSS 佈局能力。本文是關於塊格式化上下文(BFC)的。你可能從未據說過這個術語,可是若是你曾經用CSS作過佈局,你可能知道它是什麼,理解什麼是 BFC,怎麼工做以及如何建立 BFC 很是有用,這些能夠幫助你理解CSS中的佈局是如何工做的。html

在本文中,經過熟悉的示例來解釋什麼是 BFC。而後說明 display 的一個新值,只有當你理解了什麼是 BFC 以及爲何須要它時,它纔有意義。前端

想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等着你!git

什麼是 BFC

在一個Web頁面的CSS渲染中,塊級格式化上下文 (Block Fromatting Context)是按照塊級盒子佈局的。W3C對BFC的定義以下:github

浮動元素和絕對定位元素,非塊級盒子的塊級容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不爲「visiable」的塊級盒子,都會爲他們的內容建立新的BFC(塊級格式上下文)。

BFC是一個獨立的佈局環境,其中的元素佈局是不受外界的影響,而且在一個 BFC 中,塊盒與行盒(行盒由一行中全部的內聯元素所組成)都會垂直的沿着其父元素的邊框排列。segmentfault

塊格式化上下文(BFC)的行爲經過一個簡單的float示例很容易理解。在下面的示例中,我有一個框,其中包含向左浮動的圖像和一些文本。若是咱們有足夠多的文本,它會環繞浮動的圖像和邊框,而後環繞整個區域。瀏覽器

// html
<div class="outer">
  <div class="float">I am a floated element.</div>
  I am text inside the outer box.
</div>

// css
.outer {
  border: 5px dotted rgb(214,129,137);
  border-radius: 5px;
  width: 450px;
  padding: 10px;
  margin-bottom: 40px;
}

.float {
  padding: 10px;
  border: 5px solid rgba(214,129,137,.4);
  border-radius: 5px;
  background-color: rgba(233,78,119,.4);
  color: #fff;
  float: left;  
  width: 200px;
  margin: 0 20px 0 0;
}

圖片描述

若是我刪除了一些文本,那麼就沒有足夠的內容來包圍圖像,並且因爲浮動被從文檔流中脫離,因此邊框會上升,並在圖像下方,直到文本的高度。安全

圖片描述

這是由於當咱們浮動一個元素時,文本所在的框的寬度保持不變,爲給浮動元素騰出空間而縮短的是文本的行框。這就是爲何背景和邊框會出如今浮動後面的緣由。ide

咱們一般有兩種方法來解決這個佈局問題。一種方法是使用 clearfix hack,它的做用是在文本和圖像下面插入一個元素,並將其設置爲 clear:both。另外一種方法是使用 overflow 屬性,其值不是缺省值 visible佈局

.outer {
  overflow: auto;
}

圖片描述

查看演示

overflow 以這種方式工做的緣由是,使用 visible 的初值之外的任何值都會建立一個塊格式化上下文,而 BFC 的一個特性是它包含浮動。

BFC 是佈局中的一個迷你佈局

你能夠將 BFC 看做是頁面內的一個迷你佈局。一旦一個元素建立了一個 BFC,它就包含了全部的內容。正如咱們所看到的,這包括浮動的元素,它們再也不從盒子底部伸出來。BFC 還會致使一些其餘有用的行爲。

BFC 能夠防止 margin 摺疊

瞭解邊距合併是另外一個被低估的 CSS 技能。在下一個示例中,假設有一個背景顏色爲灰色的 div

這個 div 包含兩個標籤 p。外部 div 元素的 margin-bottom 爲 40 像素,標籤 p 的頂部和底部 margin 都是 20 像素。

// html
<div class="outer">
  <p>I am paragraph one and I have a margin top and bottom of 20px;</p>
  <p>I am paragraph one and I have a margin top and bottom of 20px;</p>
</div>
  
// css
.outer {
   background-color: #ccc;
  margin: 0 0 40px 0;
}

p {
  padding: 0;
  margin: 20px 0 20px 0;
  background-color: rgb(233,78,119);
  color: #fff;
}

由於 p 元素的 margin 和外部 div 上的 margin 之間沒有任何東西,因此兩個會摺疊,所以 p 最終與 div 的頂部和底部齊平。 咱們在 p 的上方和下方看不到任何灰色。

圖片描述

在CSS當中,相鄰的兩個盒子(多是兄弟關係也多是祖先關係)的外邊距能夠結合成一個單獨的外邊距。這種合併外邊距的方式被稱爲摺疊,而且於是所結合成的外邊距稱爲摺疊外邊距。摺疊的結果按照以下規則計算:

  1. 兩個相鄰的外邊距都是正數時,摺疊結果是它們二者之間較大的值。
  2. 兩個相鄰的外邊距都是負數時,摺疊結果是二者絕對值的較大值。
  3. 兩個外邊距一正一負時,摺疊結果是二者的相加的和。

產生摺疊的必備條件:margin必須是鄰接的!

若是咱們把盒子設爲 BFC,它如今包含了標籤 p 和它們的邊距,這樣它們就不會摺疊,咱們能夠看到邊距後面容器的灰色背景。

.outer {
  background-color: #ccc;
  margin: 0 0 40px 0;
  overflow: auto;
}

圖片描述

查看演示

再一次,BFC 的工做是把東西裝在盒子裏,防止它們從盒子裏跑出來。

BFC 能夠阻止元素被浮動元素覆蓋

你將熟悉 BFC 的這種行爲,由於使用浮動的任何列類型佈局都是這樣工做的。若是一個項目建立了一個 BFC,那麼該項目將不會包裹任何浮動元素。在下面的例子中,有以下 html 結構:

<div class="outer">
  <div class="float">I am a floated element.</div>
  <div class="text">I am text</div>
</div>

帶有 float 類的項被向左浮動,所以 div 中的文本在它環繞 float 以後。

圖片描述

我能夠經過將包裹文本的 div 設置爲 BFC 來防止這種包裹行爲。

.text {
  overflow: auto;
}

圖片描述

這其實是咱們建立具備多個列的浮動佈局的方法。浮動項還爲該項建立了一個 BFC,所以,若是右邊的列比左邊的列高,那麼咱們的列就不會相互環繞。

查看演示

在多列布局中使用 BFC

若是咱們建立一個佔滿整個容器寬度的多列布局,在某些瀏覽器中最後一列有時候會掉到下一行。這多是由於瀏覽器四捨五入了列寬從而全部列的總寬度會超出容器。但若是咱們在多列布局中的最後一列裏建立一個新的BFC,它將老是佔據其餘列先佔位完畢後剩下的空間。

例如:

<div class="container">
    <div class="column">column 1</div>
    <div class="column">column 2</div>
    <div class="column">column 3</div>
</div>

對應的CSS:

.column {
    width: 31.33%;
    background-color: green;
    float: left;
    margin: 0 1%;
}
.column:last-child {
  float: none;
}

未建立 BFC 以前:

clipboard.png

添加如下樣式建立一個 BFC:

.column:last-child {
  float: none;
  overflow: hidden; 
}

clipboard.png

如今儘管盒子的寬度稍有改變,但佈局不會打破。固然,對多列布局來講這不必定是個好辦法,但能避免最後一列下掉。這個問題上彈性盒或許是個更好的解決方案,但這個辦法能夠用來講明元素在這些環境下的行爲。

還有什麼能建立 BFC?

除了使用 overflow 建立 BFC 外,其餘一些 CSS 屬性還建立 BFC。正如咱們所看到的,浮動元素建立了 BFC。你的浮動項將包含它裏面的任何東西。

使用如下方式都能建立 BFC

  • float 的值不是 none。
  • position 的值不是 static 或者 relative。
  • display 的值是 inline-block、table-cell、flex、table-caption 或者inline-flex
  • overflow 的值不是 visible

建立 BFC 的新方式

使用overflow或其餘的方法建立BFC時會有兩個問題。首先,這些方法自己是有自身的設計目的,因此在使用它們建立BFC時可能會產生反作用。例如,使用overflow建立BFC後在某些狀況下可能會看到出現一個滾動條或者元素內容被裁切。

這是因爲overflow屬性的設計是用來讓你告訴瀏覽器如何定義元素的溢出狀態的。瀏覽器執行了它最基本的定義。

即便在沒有任何不想要的反作用的狀況下,使用 overflow 也可能會讓其餘開發人員感到困惑。爲何 overflow 設置爲 autoscroll?最初的開發者的意圖是什麼?他們想要這個組件上的滾動條嗎?

最安全的作法應該是建立一個 BFC 時並不會帶來任何反作用,它內部的元素都安全的呆在這個迷你佈局中,這種方法不會引發任何意想不到的問題,也能夠理解開發者的意圖。CSS 工做組也十分認同這種想法,因此他們定製了一個新的屬性值:display:flow-root

flow-root 瀏覽器支持狀況

你可使用display:flow-root安全的建立BFC,來解決上文中提到的各類問題:包裹浮動元素、阻止外邊距疊加和阻止圍繞浮動元素。

圖片描述

瀏覽器對該屬性的支持目前仍是有限的,若是你以爲這個屬性值很方便,請投票去讓Edge也支持它。不過不管如何,你如今應該已經理解了什麼是 BFC,以及如何使用 overflow 或其餘方法來包裹浮動,以及知道了 BFC 能夠阻止元素去環繞浮動元素,若是你想使用彈性或網格佈局能夠在一些不支持他們的瀏覽器中使用 BFC 的這些特性作降級處理。

理解瀏覽器如何佈置網頁是很是基礎的。 雖然有時看起來可有可無,可是這些小知識能夠加快建立和調試 CSS 佈局所需的時間。

你的點贊是我持續分享好東西的動力,歡迎點贊!

交流

乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。

https://github.com/qq44924588...

我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!

關注公衆號,後臺回覆福利,便可看到福利,你懂的。

clipboard.png

相關文章
相關標籤/搜索