CSS中關於定位及BFC中的易錯點

提及BFC,就必須先了解一下CSS文檔流中的定位機制,並且這部分說簡單也簡單,但卻有個坑有可能誤導咱們,特在本文做出解釋。html

1、文檔流中的定位機制

1. 三種基本方式

CSS有三種基本定位機制,我想大多數朋友都掌握了,在此簡要概述一下(不浪費時間):面試

  1. 普通流(或稱常規流):CSS默認的定位方式,觸發方式包括爲position: static/relative,且float:none
  2. 浮動:浮動脫離普通流,能夠左右移動,直到它的外邊框邊緣碰到包含框或另外一個浮動框的邊緣,觸發方式基本就是float:left/top等。
  3. 絕對定位:盒子脫離普通流,不影響普通流上其餘元素的佈局

2. 注意事項

因此,此時大部分初學者都會結合現實世界感受到這三種流的立體感就是以下圖所示的這樣: bash

image

這裏我想說的是,上圖這種表達方式不能說是徹底正確,雖然層級明確了,但這會給初學者帶來錯誤的理解:浮動元素既然已經玩飄了,且普通流中的div也不會再給它留地方了,那浮動元素對普通應該就完全沒影響了吧? 固然不是! 直接上個小例子看看(多餘上色之類的代碼去掉了):佈局

<body>
  <div class='parent'>
    <div class='child1'>
       Child1
    </div>
	<div class='child2'>
	    冷咖啡離開了杯墊
		我忍住的情緒在很後面
	</div>
  </div>
</body>
<style>
.parent {
  width:400px;
  min-height:100px;
}
.child1 {
  width:50px;
  height:50px;
}
.child2 {
  width:100px;
  height:100px;
}
</style>
複製代碼

效果以下:post

image

好的,那接下來,按照咱們的想法,把child1設爲浮動,此時它就應該脫離普通流,且普通流中的元素再也不考慮它的位置了,child1添加float:left後以下:學習

image

咦!child1確實感受浮動了,child2也確實絕不客氣的把child1本來的位置給頂替了, 可child2裏面的元素是咋回事?爲何像躲摔倒的老太太同樣躲避child1了呢? 這就是我想提醒朋友們必定要注意的地方。下面看看解釋:flex

float起初被設計出來的初衷實際上是爲了實現報紙上的那種文字環繞圖片的效果,就像咱們上例這種普通流中的文字環繞在child1的周圍。但以後你們才發現結合float + div 能夠實現必定的網頁佈局,因此,這是浮動的特性。即浮動只是脫離了文檔流,即不會按照你的設計而進行佈局,就算它在任何位置上那也是和文檔流中的其餘內容是是平級關係的,咱們在使用浮動時,基本上就考慮它的佈局定位就好了,不要以爲它完全飄了,它的影響還在。ui

好了,這個坑幫不知道的朋友解決了,接下來就好理解BFC了。spa

2、BFC探索之路

你可能在不知道BFC是啥玩意的前提下卻知道解決子div浮動而形成父div塌陷的一個經典的辦法就是給父div設置overflow:hidden,但要是面試官問你爲啥,你可能就歇菜了,別問我怎麼知道,我曾經就是那個菜雞...,因此,瞭解了BFC,你就知道爲啥了。設計

1. BFC概念

BFC(Block Formatting Context,塊格式上下文)是Web頁面的可視化CSS渲染的一部分,而且有自身的一套渲染規則,它決定了其子元素如何定位,以及和其餘元素的關係和相互做用。

2. BFC特色

具備BFC特性的元素能夠當作是隔離了的獨立容器,容器裏面的元素不會在佈局上影響到外面的元素,而且BFC具備普通容器所沒有的一些特性。不少好的文章羅列的內容有:

  1. 內部的box會在垂直方向,從頂部開始一個接一個地放置;
  2. box垂直方向的距離由margin決定,屬於同一個BFC的兩個相鄰的box的垂直方向的margin會發生疊加;
  3. 在BFC中,每一個盒子的左外邊緣(margin-left)會觸碰到容器的左邊緣(border-left)。對於從右到左的格式來講,則觸碰到右邊緣,即便是浮動的也是如此,即不會發生margin穿透;
  4. 造成了BFC的區域不會與float box重疊;
  5. 計算BFC高度時,子浮動元素也參與計算(BFC會確切包含浮動的子元素,即閉合浮動);

【補充 2019/04/10】 針對2的內容,有朋友提出了,普通佈局流中,同一個父box(不管是不是BFC)的兩個相鄰的box元素的垂直方向任然也會發生重疊。是的,但若是父box是個BFC,那它存在以下特色: (1) 普通流中,若是父box的直屬子box設定了垂直margin,則它並不會撐大父元素,效果以下:

上圖中,設定兩個子元素p爲margin:20px 0,能夠看到p之間有重疊,但它們和父box元素的間距是0;

(2)針對上述問題,若是把父box設爲BFC(給一個overflow:hidden),則效果以下:

這下父box就被撐開啦,但此時子box之間的垂直方向的margin仍然是重疊的。

因此,再遇到下面這些問題時,就能夠回答了:

  1. 如何保證一個div元素不被同級的浮動元素覆蓋:設置該div元素爲BFC;
  2. 爲何父div設置overflow:hidden就能夠在其子div爲浮動的狀況下依然能夠撐開:由於此時父div是個BFC。

可是!這裏我還想說一下個人一些想法,即:我認爲,之因此提出BFC的概念,其主要目的是爲了隔離出獨立容器,而容器自己與其餘元素之間是否徹底知足上述特性,這應該區別對待,咱們應該把BFC的核心思惟用在它自己內部而非外部,後面文章會有例子。

3. 觸發BFC的條件

有朋友羅列了好多,記住一些常規的便可:

  1. 根元素或包含根元素的元素,這裏應該就是body元素
  2. 浮動元素(float不是none);
  3. 絕對定位元素(position:absolute/fixed);
  4. 行內塊元素(display:inline-block);
  5. 表格單元格(display:table-cell ,html表格單元格默認爲該值);
  6. 表格標題(display:table-caption , html表格標題默認爲該值);
  7. 匿名錶格單元格元素(display:table / table-row / table-row-group / table-header-group / table-footer-group / inline-table ,分別是html table 、row、tbody、thead、tfoot的默認屬性);
  8. overflow:非visible塊元素;
  9. display:flow-root;
  10. contain:layout / content / strict;
  11. 彈性元素(display:flex / inline-flex 元素的直接子元素);
  12. 網格元素(display:grid / inline-grid 元素的直接子元素);
  13. 多列容器(元素的column-count 或 column-width 不爲 auto,且包括 column-count爲1);
  14. column-span 爲all 的元素始終會建立一個新的BFC,即便該元素沒有報過在一個多列容器中;

因此,每次看到 overflow:hidden、float:left/right 、position:absolute/fixed ,不用懷疑,必定是BFC

4. 實際使用場景

BFC在實際開發佈局中基本能夠作這兩件事:

  1. 避免因爲子元素浮動形成父元素塌陷;
  2. 避免同一個BFC中的兩個塊級元素的垂直方向margin重疊(設置其中一個爲一個新的BFC,永久隔絕外部影響);
  3. 自適應兩欄佈局。

5. BFC實例

直接看看吧

<body>
    <div class='box'>
	   <div class='left'>左邊</div>
	   <div class='right'>右邊
		 <div class='little'>1</div>
		 <div class='little'>2</div>
		 <div class='little'>3</div>
	   </div>
	</div>
</body>
<style>
.box {
  background:#888;
  overflow:hidden;
  margin-left:50px;
}
.left {
  background: #73DE80; /* 綠色 */
  width:200px;
  height:200px;
}
.right {
  background: #EF5BE2; /* 粉色 */
  width:400px;
  min-height:100px;
}
.little {
    background: #fff;
	width: 50px;
	height: 50px;
	margin: 10px;
	float:left;
}
</style>
複製代碼

效果以下:

image

若是忽然把div left元素 添加一個float:left:

image

看到了吧!div right元素的子元素騰地方了,那接下來把div right變成一個BFC,好比使用:overflow:hidden,效果以下:

image

這樣,就知足了BFC內部元素不受外界干擾,且不會與float元素重疊兩個特性。

可是,若是我給box right 元素設置了絕對定位,那它是會覆蓋box left這個浮動元素的,可這就不符合BFC的不會與float元素重疊這個特性了

image

因此我提出了我和我同事討論出的想法,即咱們不能把上述羅列的BFC特性完全確定,由於這裏涉及到的是兩個大的知識層。當設置了絕對定位,雖然也觸發了BFC,可是它更是直接影響了層級關係,因此優先實現後者。

以上就是我想提醒廣大和我同樣的初級朋友,歡迎你們批評指正,謝謝您!!!~~~

參考文獻
  1. 《學習 BFC》 juejin.im/post/59b73d…
  2. 《關於BFC理解》 reng99.cc/2018/08/12/…
相關文章
相關標籤/搜索