關於BFC的一些事

来源:https://www.cnblogs.com/yyong/archive/2019/09/12/11510212.html
-Advertisement-
Play Games

BFC的生成 在實現CSS的佈局時,假設我們不知道BFC的話,很多地方我們生成了BFC但是不知道.在佈局中,一個元素是block元素還是inline元素是必須要知道的.而BFC就是用來格式化塊狀元素盒子,同樣還有管理內連盒子的IFC等.那首先就來瞭解一下什麼是FC. 既然BFC是一塊獨立的渲染區域, ...


BFC的生成

在實現CSS的佈局時,假設我們不知道BFC的話,很多地方我們生成了BFC但是不知道.在佈局中,一個元素是block元素還是inline元素是必須要知道的.而BFC就是用來格式化塊狀元素盒子,同樣還有管理內連盒子的IFC等.那首先就來瞭解一下什麼是FC.

FC: Formatting Context指的是頁面中的一個渲染區域,並且擁有自己的渲染規則.決定子元素如何定位,以及和其他元素的相互作用和聯繫.
BFC: 塊級格式化上下文, 是一個獨立的塊級渲染區域,只針對塊級元素,有一套自己的渲染規則來約束塊級盒子,與外部無關.

既然BFC是一塊獨立的渲染區域,那麼這塊區域在哪裡,有多大, 這就有生成BDC的元素決定,CSS2.1中規定, 滿足以下CSS聲明的元素就會生成BFC.

  • 根元素
  • float不為none
  • overflow不為hidden
  • display: inline-block, table-cell, table-caption(註意: 值為table會生成BFC是因為會預設生成一個匿名的table-cell,所以不是table生成了BFC)
  • position: absolute, fixed
 

BFC的約束

瀏覽器對BFC約束如下:

1. 生成BFC的子元素會一個接一個的放置,在垂直方向上的起點是包含塊的頂部,相鄰的子元素之間的垂直距離由margin控制.在BFC中相鄰的塊級元素外邊距會摺疊.
2. BFC中的子元素中,每一個子元素的左外邊距與包含塊的左邊界接觸(從右到左的格式化,與右邊界接觸),即使浮動元素也如此,除非這個子元素也創建了BFC.

具體展開來說就是:
1. 內部Box在垂直方向上一個接一個放置
2. 垂直方向的距離由margin決定.
3. 每個元素的左外邊距與包含塊的左邊界接觸,即使浮動元素也是如此.所以BFC中的元素不會超出包含塊,但是position為absolute的元素可以超出包含塊的邊界.
4. BFC的區域不會與float元素的區域重合.
5. 計算BFC的高度會包含float元素,但是float元素會使父元素高度塌陷.註意區別BFC高度和父元素高度.
6. BFC相當於頁面上的一個獨立的容器.子元素不影響外部元素,反之亦然.
所以看到這些約束,一些常見的規則就可以瞭解原因.比如:

- 塊級元素與父元素同寬,垂直排列
- 垂直方向上的相鄰div的外邊距會摺疊
- 浮動元素會儘量接近左上方
- 父元素浮動,或者overflow為hidden會包住子元素
 

BFC在佈局中的應用

 

1. 解決margin摺疊

同一個BFC中的兩個相鄰Box才會發生重疊與方向無關,不過由於上文提到的第一條限制,我們甚少看到水平方向的margin重疊。這在IE中是個例外,IE可以設置write-mode

 
  1. <!doctype HTML>
  2. <html>
  3. <head>
  4. <style type="text/css">
  5. #green {
  6. margin:10px 10px 10px 10px
  7. }
  8. #blue {
  9. margin:10px 10px 10px 10px
  10. }
  11. #red {
  12. margin:10px 10px 10px 10px
  13. }
  14. body {
  15. writing-mode:vertical-rl;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <div id="green" style="background:lightgreen;height:100px;width:100px;"></div>
  21. <div id="blue" style="background:lightblue;height:100px;width:100px;"></div>
  22. <div id="red" style="background:pink;height:100px;width:100px;"></div>
  23. </body>
  24. </html>

可以看到水平方向發生了重疊
水平方向摺疊

要阻止margin重疊,只要將兩個元素別放在一個BFC中即可(可以用上文提到的方式讓相鄰元素其中一個生成BFC)。阻止兩個相鄰元素的margin重疊看起來沒有什麼意義,主要用於嵌套元素。

 
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5. <!--The viewport meta tag is used to improve the presentation and behavior of the samples
  6. on iOS devices-->
  7. <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
  8. <title></title>
  9. <style>
  10. html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
  11. .first{
  12. margin:20px;
  13. background:lightgreen;
  14. width:100px;
  15. height:100px;
  16. }
  17. ul{
  18. /*display:inline-block;*/
  19. margin:10px;
  20. background:lightblue;
  21. }
  22. li{
  23. margin:25px;
  24. }
  25. </style>
  26. </head>
  27. <body>
  28. <div class="first"></div>
  29. <ul>
  30. <li>1</li>
  31. <li>2</li>
  32. <li>3</li>
  33. </ul>
  34. </body>
  35. </html>

此時div與ul之間的垂直距離,取div、ul、li三者之間的最大外邊距。
外邊距取最大值
要阻止嵌套元素的重疊,只需讓ul生成BFC即可(將代碼中飯的display註釋去掉),這樣div、ul、li之間便不會發生重疊現象。而li位於同一BFC內所以仍然存在重疊現象。

 

2. 解決浮動

在清楚浮動帶來的問題的解決方案中,一定會回答用BFC清除,那到底是怎麼清除的呢?根本原因就是父級元素創建BFC後,子元素即使浮動也會參與BFC高度的計算.即不會產生高度塌陷的問題.

 
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>JS Bin</title>
  6. <style>
  7. html, body {
  8. height: 100%;
  9. width: 100%;
  10. margin: 0;
  11. padding: 0;
  12. }
  13. .first{
  14. margin:20px;
  15. background:lightgreen;
  16. border: 2px solid lightgreen;
  17. /*display:inline-block;*/
  18. /*overflow:hidden;*/
  19. /*float: left;*/
  20. /*position: absolute;*/
  21. }
  22. ul{
  23. overflow:hidden;
  24. margin:10px;
  25. background:lightblue;
  26. width:100px;
  27. height:200px;
  28. float: left;
  29. }
  30. li{
  31. margin:25px;
  32. }
  33. </style>
  34. </head>
  35. <body>
  36. <div class="first">
  37. <ul>
  38. <li>1</li>
  39. <li>2</li>
  40. <li>3</li>
  41. </ul>
  42. </div>
  43. </body>
  44. </html>

父元素
將代碼中first樣式中任意一項註釋去掉都可以得到包圍浮動的效果,其中overflow:hidden方式,與正常流最接近。
關於清除浮動的詳細介紹,請參考這篇簡潔明瞭的文章.

 

3. 多欄佈局的BFC實現

通過BFC約束: BFC的區域不會與float的元素區域重疊, 可以來實現多欄佈局.

 
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>JS Bin</title>
  6. <style>
  7. html, body {
  8. height: 100%;
  9. width: 100%;
  10. margin: 0;
  11. padding: 0;
  12. }
  13. .left{
  14. background:pink;
  15. float: left;
  16. width:180px;
  17. }
  18. .center{
  19. background:lightyellow;
  20. overflow:hidden;
  21. }
  22. .right{
  23. background: lightblue;
  24. width:210px;
  25. float:right;
  26. }
  27. </style>
  28. </head>
  29. <body>
  30. <div class="container">
  31. <div class="left">
  32. <pre>
  33. .left{
  34. background:pink;
  35. float: left;
  36. width:180px;
  37. }
  38. </pre>
  39. </div>
  40. <div class="right">
  41. <pre>
  42. .right{
  43. background:lightblue;
  44. width:180px;
  45. float:right;
  46. }
  47. </pre>
  48. </div>
  49. <div class="center">
  50. <pre>
  51. .center{
  52. background:lightyellow;
  53. overflow:hidden;
  54. height:116px;
  55. }
  56. </pre>
  57. </div>
  58. </div>
  59. </body>
  60. </html>

這種佈局的特點在於左右兩欄寬度固定,中間欄可以根據瀏覽器寬度自適應。
多欄佈局

 

收穫

初次看到BFC這個詞,是在一個面試題上.然後百度了一下,看到了寒冬大神的一篇博客,當時看完是覺得BFC,對於大佬來說是必要的,對我而言還太早.確實,當時的我還是一個連佈局什麼都不是很懂的菜鳥(當然現在也是).在看了一些CSS的基礎之後,通過查閱資料,在這裡提及一下,最新的佈局方案Flex和Grid都會生成BFC,具體可以去看MDN,看一些前輩的心得,總是覺得會了,但是過段時間就忘掉了.俗話,能給別人講明白才是真正的理解了.所以才絞盡腦汁寫了這樣一個總結.

其實對於BFC,我們只要知道一些特定的CSS聲明會生成BFC,瀏覽器對BFC有一套特定的渲染規則,利用這些特殊的規則在佈局上解決一些問題,就差不多了.但是當深入理解之後,會發現很多最常見的效果,就是因為BFC.當探究到這些的時候,前端的樂趣就在這裡了.

文章中的內容可能有很問題,希望不吝指導.畢竟工作經驗對於我還是欠缺的,遇到問題探究問題的方式方法不一樣.不過話說回來,技術的樂趣就在於不斷的探究,試錯,總結積累上.

最後提一下IE,在IE中有類似的hasLayout.有興趣可以研究研究.


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在之前的《JavaScript對象基礎》中,我們大概瞭解了對象的創建和使用,知道對象可以使用構造函數和字面量方式創建。那麼今天,我們就一起來深入瞭解一下JavaScript中的構造函數以及對象的原型及原型鏈。 一 構造函數 1,什麼是構造函數 Javascript中使用構造函數的目的是批量創建擁有相 ...
  • 前戲 到目前為止,我們已經學過了JavaScript的一些簡單的語法。但是這些簡單的語法,並沒有和瀏覽器有任何交互。 也就是我們還不能製作一些我們經常看到的網頁的一些交互,我們需要繼續學習BOM和DOM相關知識。 JavaScript分為 ECMAScript,DOM,BOM。 BOM(Browse ...
  • 一.模板缺陷 模板的最大特點是擴展難度大,不易擴展。可能會造成邏輯冗餘 Level組件需要對不同的type產生不同的標簽 二.函數式組件 函數式組件沒有模板,只允許提供render函數 複雜的邏輯變得非常簡單 三.JSX應用 使用jsx會讓代碼看起來更加簡潔易於讀取 四.render方法訂製組件 編 ...
  • "在這裡閱讀效果更佳" 還記得當年和同桌在草稿紙上下三子棋的時光嗎 今天我們就用代碼來重溫一下年少(假設你有react基礎,沒有也行,只要你會三大框架的任意一種,上手react不難) 游戲規則 + 雙方各執一子,在九宮格內一方三子連成線則游戲結束 + 九宮格下滿未有三子連線則視為平局 "你可以點擊這 ...
  • 1.創建XMLHttpRequest let xhr=new XMLHttpRequest; 2.連接伺服器 xhr.open("get","goods.json",true) true代表非同步,false代表同步。goods.json代表請求的路徑 3.向伺服器發送請求 xhr.send() 4. ...
  • <script> //js獲取頁面所有搜索條件function GetSearchData(SearchDivID) { var ObjID= SearchDivID? SearchDivID: ".search"; //預設為類樣式.search, <div class="search"> var ...
  • VUE中CSS樣式穿透 1. 問題由來 在做兩款H5的APP項目,前期採用微信官方推薦的weui組件庫。後來因呈現的效果不理想,組件不豐富,最終項目完成後全部升級採用了有贊開發的 組件庫。同時將webpack順利從3升級到4(項目結構 webpack+vue+vuex+vue router+vant ...
  • 作者:西西 最近很流行的一句話成年人的世界沒有「容易」二字,其實程式員的世界更沒有『容易』二字。不是電腦專業出身的我初入行的時候,每晚在樓下的全時便利店敲代碼到深夜 1 - 2 點。但這其實僅僅是開始,努力了幾個月以後成功面試進入一家互聯網公司(剛入職場薪資很低),自此開啟了我的代碼職業生涯。 初 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...