【Web前端HTML5&CSS3】10-高度塌陷與BFC


筆記來源:尚硅谷 Web 前端 HTML5&CSS3 初學者零基礎入門全套完整版

高度塌陷與 BFC

1. 高度塌陷

在浮動布局中,父元素的高度默認是被子元素撐開的

當子元素浮動后,其會完全脫離文檔流,子元素從文檔流中脫離將會無法撐起父元素的高度,導致父元素的高度丟失

父元素高度丟失以后,其下的元素會自動上移,導致頁面的布局混亂

動畫2021-41

所以高度塌陷是浮動布局中比較常見的一個問題,這個問題我們必須要進行處理!

img

別急,我們接着往下看

2. BFC

BFC(Block Formatting Context)塊級格式化環境

  • BFC 是一個 CSS 中的一個隱含的屬性,可以為一個元素開啟 BFC
  • 開啟 BFC 該元素會變成一個獨立的布局區域

元素開啟 BFC 后的特點:

  • 不會被浮動元素覆蓋
  • 父子元素外邊距不會重疊
  • 可以包含浮動的元素

img

可以通過一些特殊方式來開啟元素的 BFC:

  • 設置為浮動(不推薦):很明顯下方元素被覆蓋了,總不能讓所有元素都浮動吧

    動畫2021-40

  • 設置為行內塊元素(不推薦):不再獨占一行,寬度變了,同時與下方元素產生了一點空隙

    動畫2021-39

  • 設置overflow為非visible:既沒有覆蓋元素,也保持了獨占一方的特性(保持了寬度),與下方元素也保持了最初的間隙

    常用的方式為元素設置overflow:hiddenoverflow:auto也是 ok 的) 開啟其 BFC, 以使其可以包含浮動元素

    overflow:scroll 會有滾動條,可能並不需要的,所以不太推薦

    動畫2021-38

    不過,這種方式也存在一定問題,如下,overflow並沒有完全清除 div2 布局上受到的影響

    動畫2021-34

總結

  • 可以通過變成浮動元素,來防止自身被浮動元素覆蓋(有點“以毒攻毒”那味了)
  • 可以設置行內塊,來防止自身及其他元素被浮動元素覆蓋(如果說浮動是“獨善其身”,那行內塊就有點“兼濟天下”的意思)
  • 可以設置overflow屬性,包含浮動元素(既“獨善其身”,又“兼濟天下”,但仍有缺陷)

img

img

我們可以打開Zeal手冊(《02-前端開發准備》有介紹),查看關於 BFC 的說明文檔

image-20210526210723927

打開Block formatting context模塊后,可以看到有很多開啟 BFC 的方式

image-20210526210843339

我這里大概翻譯了一下,並整理了一份表格,應該看起來更直觀一點(有些概念因為還沒有學習,翻譯和理解有誤的地方還望諒解)

元素或屬性 說明
<html> 文檔根元素
float: left
float: right
浮動元素(float不為none
position: absolut
position: fixed
絕對定位元素
display: inline-block 行內塊元素
display: table-cell 表格單元,默認值
display: table-caption 表格標題,默認值
display: table
display: table-row
display: table-row-group
display: table-header-group
display: table-footer-group
display: inline-table
匿名的表格單元,分別是 HTML 表格、表行、表體、表頭和表腳的默認值
overflow: hidden
overflow: scroll
overflow: auto
overflow不為visibleclip的塊元素
display: flow-root
contain: layout
contain: content
contain: paint
display: flex
display: inline-flex的直接子元素
Flex 項,如果它們本身既不是flex,也不是gridtable容器
display: grid
display: inline-grid的直接子元素
Grid 項,如果它們本身既不是flex,也不是gridtable容器
column-count不為auto
column-width不為auto
Multicol 容器,包含column-count: 1
column-span: all 應該總是創建一個新的格式化上下文,即使column-span: all元素不在 multicol 容器中

但是,注意不管哪種方式,多多少少都會有些隱患、缺陷或者說“副作用”

image-20210526231648421

3. clear

我們這里設計三個兄弟元素,對前兩個元素進行float的浮動屬性設置,看下效果

動畫2021-36

由於 box1 的浮動,導致 box3 位置上移也就是 box3 受到了 box1 浮動的影響,位置發生了改變(注意,這里文字並沒有被覆蓋,《09-浮動》一節說過浮動的特點,其中第 7 點就是“文字環繞”的問題)

img

如果我們不希望某個元素因為其他元素浮動的影響而改變位置,可以通過clear屬性來清除浮動元素對當前元素所產生的影響

clear作用:清除浮動元素對當前元素所產生的影響(本質是為元素添加一個margin-top屬性,值由瀏覽器自動計算)

可選值:

  • left 清除左側浮動元素對當前元素的影響
  • right 清除右側浮動元素對當前元素的影響
  • both 清除兩側中影響較大一側元素的影響(注意,這里不是同時清除兩側的影響)

動畫2021-37

4. after

我們學習了上面知識后,了解了高度塌陷問題的解決方式,其中主要有

  • 通過overflow: hidden等可以為元素開啟 BFC

    動畫2021-35

  • 通過clear: both等可以清除浮動對元素產生的影響

    動畫2021-33

同時也了解到,這兩種方式都有一定的弊端和隱患。那有沒有一種更好的方式去解決高度塌陷的問題呢?

答案當然是:有!

image-20210526233234635

我們直接上效果圖

動畫2021-32

Q1:這里使用了一個偽元素選擇器::after,那有人會問了,跟在 box2 下直接定義一個 box3 有什么區別呢?

A:我們知道,網頁的結構思想是:結構+表現+行為。在 box2 下直接定義一個 box3,屬於結構;而使用偽元素選擇器,屬於表現

而高度塌陷問題屬於表現問題,定義 box3 的目的是為了撐起 box1 的內容,屬於表現,而不是結構,所以在 css 中定義::after更符合網頁的編程思想

Q2:為什么需要使用display: block呢?

A:因為默認情況下,::after偽元素是一個行內元素,如果不轉為塊元素,將仍然撐不起 box1 的高度

image-20210526235431125

5. clearfix

我們在前面《06-盒模型》一節中說過垂直布局中邊距重疊的問題:相鄰的垂直方向外邊距會發生重疊現象

動畫2021-30

如上圖所示,子元素設置了一個margin-top之后,父元素跟隨子元素一起進行了移動

即我們之前說的父子元素間相鄰外邊距,子元素會傳遞給父元素(上外邊距)

聰明的小伙伴已經想到了,用剛才說的偽元素選擇器啊

img

好,我們先來看下效果

動畫2021-29

貌似是沒有任何變化,到底是什么地方不對呢?

img

我們再來回顧下使用after偽元素的心路歷程:

  • 使用無內容的 box3 撐起 box1 ==》表現代替結構(::after代替 box3)
  • clear清除浮動對元素產生的影響(還記得clear的原理么?)

img

其實就是給元素設置了一個margin-top屬性,不過這個在開發者工具中是看不到的

既然如此,就相當於在 box2 下面添加一個 box3,然后給 box3 設置一個margin-top屬性

到此為止,

相鄰的垂直方向外邊距 這個條件仍然滿足

會發生重疊現象這個結論也依然成立

具體點就是,父子元素間相鄰外邊距,子元素會傳遞給父元素(上外邊距),表現為 box1 和 box2 同步往下移動

那我們應該怎么做才能解決這個問題? 憑你們朴素的情感,應該怎么判? 當然就是讓上述條件不滿足唄!

怎么能夠不滿足?當然是讓兩個元素垂直外邊距不相鄰啊!

好,多說無益,我們直接上代碼看效果!

動畫2021-28

我們用了before偽元素選擇器,目的當然是讓 box1 和 box2 的外邊距不相鄰,但是好像並沒有效果

我們再換成display: inline-block屬性看看

動畫2021-27

好像是解決了父元素布局的問題,但是子元素怎么還往下跑了一段距離? 是誰給的勇氣?

因為inline-block兼顧行內元素和塊元素的特點,既可以設置寬高也不獨占一行

在沒有設置寬高時,會存在一個默認高度,所以inline-block仍然行不通

還有一個屬性,display: table

動畫2021-26

Bingo!實現了我們最終想要的效果

Q1:為什么沒有使用 clear 屬性?

A:不是說了嗎?clear是為了清除浮動對布局的影響,我們現在沒有浮動的元素啊,我們要討論的也不是浮動的問題

Q2:display 不是還有一個none屬性么,為什么不用呢?

A:none屬性是不占據位置,但是也不能讓元素相鄰的外邊距分離啊

Q3:為什么table值就可以呢?

A:這個問題問的非常好,算是問到點上了!我們上面在講開啟 BFC 的一些方法的時候,也提到了該屬性。而且,應該牢記的是,元素開啟 BFC 后的其中一個特點就是 父子元素外邊距不會重疊。當然,這里也需要合理選擇偽元素選擇器,使其外邊距不相鄰才行

另外,總結一下:

  • 高度塌陷問題,一般用::after
  • 外邊距重疊問題,一般用::before

不知道到這里,大家能不能想明白這兩件事情

img

那么問題來了,有沒有一個兩全其美的辦法,既可以解決高度塌陷,又可以解決外邊距重疊呢?

img

當然有!clearfix 這個樣式就可以同時解決高度塌陷和外邊距重疊的問題

當你在遇到這些問題時,直接使用clearfix這個類即可,他就可以幫你輕松搞定 css 中的兩大難題

.clearfix::before,
.clearfix::after {
  content: "";
  display: table;
  clear: both;
}

其中.clearfix::before是為了解決外邊距重疊問題

.clearfix::before {
  content: "";
  display: table;
}

.clearfix::after是為了解決高度塌陷問題

.clearfix::after {
  content: "";
  display: table;
  clear: both;
}

兩者合在一起,就可以完美地解決高度塌陷和外邊距重疊這兩大“世紀難題”了

image-20210528030932616


免責聲明!

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



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