博客 / 詳情

返回

Html—BFC

背景

BFC,即Block Format Context,塊級格式化作用域,我們先不管它的目的是什麼,先來了解下格式化作用域的相關類型。

格式化作用域的類型

文檔流中的行內元素和塊級元素,都屬於格式化作用域,所以格式化作用域有兩種類型:

  • 塊級格式化作用域
  • 行內格式化作用域

格式化作用域的作用

格式化作用域,規定了當前節點內部的文檔流不受外界文檔流的影響。
(原因很簡單啊,因為除了正常文檔流還有其他形式的文檔流,比如float、fixed、absolute等方式會脱離當前正常文檔流)
説白了就是,html和css的一種約定,如果沒有這種約定,瀏覽器去解析下面的代碼

// html
<div class="normal">
    <div class="absolute">
        <div class="son"></div>
    </div>
</div>

//css
.normal {
    position: relative;
}
.absolute {
    position: absolute;
}
.son {
    position: relative;
}

對於normal和absolute兩個div可以進行正常的解析,那son這個div應該怎麼解析這個div?是屬於noraml內部的還是absolute內部的?瀏覽器就不知道怎麼辦了,而
有了這種約定,就可以講son解析為absolute的節點,對文檔進行更好的解析,然後呈現在瀏覽器上面。

塊級格式化作用域

如何觸發塊級格式化作用域?

  • 浮動元素
  • 絕對定位元素
  • 不是塊狀盒子的盒子(比如inline-block/table-cells/table-captions)
  • overflow不為visible的元素

塊級化格式化作用域內部元素如何排列?

  • 盒子從上到下排列
  • 盒子的左側邊界挨着父節點的左側邊界
  • 盒子之間的垂直距離取決於margin,可能會發生外邊距摺疊

外邊距摺疊

外邊距摺疊也不是一定會發生的,下面兩種情況就不會發生摺疊:

  • 根節點元素的盒子不會摺疊(如果這都摺疊,那最外層div的margin就無效了)
  • 水平元素之間永遠不會發生外邊距摺疊
  • 塊級元素在當前格式化作用域內部(必須是塊級元素,不能是inline-block)
  • 清除浮動,沒有padding和border分割(border為0無效)

外邊距摺疊發生的位置

  • 父節點和第一個子節點的margin-top
  • 子節點的margin-bottom和下一個相鄰節點的margin-top
  • 如果父節點的高度是自動計算的auto,那麼父節點的margin-bottom和其最後一個子節點margin-bottom

總結起來,就是margin可能會在圖中3個地方發生摺疊:

摺疊後margin計算

  • margin,都為正,取最大的那一個
  • margin,一正一負,兩者相加
  • margin,都為負,取絕對值最大的那一個

如何避免外邊距摺疊?

既然外邊距摺疊發生在圖中三個位置,那麼我們就看看三個位置不發生摺疊的情況

通用情況
  • 如果創建了塊級格式化作用域
位置1: 父節點和第一個子節點
  • 如果父節點具備border和padding,那麼就不會發生摺疊
  • 第一個div 具備clear
位置2: 相鄰節點之間
  • 詳細通用情況
位置3: 父節點和最後一個子節點
  • 通用情況
  • 父節點沒有規定高度,height:auto並且min-height:0
  • 如果父節點具備border和padding,那麼就不會發生摺疊
注意⚠️

如果子節點中有浮動元素,並且其他節點具備clear:both/left/right,那麼就會把兄弟元素放在浮動元素的邊界下方,但是依然會發生外邊距摺疊。

行內格式化作用域

如何觸發?

行內元素,比如span等等

內部如何排列?

從左到右,不會發生外邊距摺疊

行內格式化元素的寬度

寬度取決於包含內容的寬度,如果屏幕足夠寬,就會把所有的內容一行展示,如果設置了寬度,可能還有overflow,舉個例子:

<P>Several <EM>emphasized words</EM> appear
<STRONG>in this</STRONG> sentence, dear.</P>

瀏覽器在解析的時候,會解析為下面的幾個元素:

Anonymous: "Several"
EM: "emphasized words"
Anonymous: "appear"
STRONG: "in this"
Anonymous: "sentence, dear."

但是可能會解析為一個或者幾個line-box,瀏覽器會做對應的分割,
可能是一個line-box:

 Several emphasized words appear in this sentence, dear.

可能是兩個line-box:

Several emphasized words appear
in this sentence, dear.

也可能是三個line-box:

Several emphasized  
words appear in this 
sentence, dear.

具體的分割原理是取決於對應的line-height能不能相互平衡。
當然如果你設置了具體寬度,可以設置換行等其他屬性,比如white-space/word-break等,這裏就不做贅述了。

行內格式化元素的高度

inline的高度取決於line-height,但是inline-block類別的(還有table-cell等),取決於margin等。總結起來一句話就是,line-height的高度是盒子頂點到底部之間的距離

具體計算

  • font-size: 每一個line-box都有一個屬性font-size,如果沒有設置,使用默認值,或者繼承自父節點的值(pc端谷歌瀏覽器的默認值14px)
  • line-height: 規定了line-box的最小高度,也就是line-box的高度

在line-box裏面,vertical-align,其中的baseline,就是通過line-height計算得來的,主要包括下面三個部分:

  • A(base-line上面的高度)
  • D(base-line下面的高度)
  • L(line-height — A - D)

最終baseline上面的高度:A + L/2, baseline下面的高度: D + L/2
當然,具體的A和D取決於瀏覽器的標準和不同的文字的標準,畢竟英文和中文對應的就不一樣。

參考

1、BFC
2、line-height

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.