面試之CSS篇 - 邊距重疊與BFC

不吃早餐發表於2019-03-11

本文主題:

  • 基本概念: 標準模型 + IE 模型
  • 基本模型和 IE 模型的區別:計算寬度和高度的不同
  • CSS 如何設定這兩種模型(由理論轉為運用)
  • JS 如何設定、獲取盒模型對應的寬和高
  • 例項題(根據盒模型解釋邊距重疊問題) 拔高性的延伸
  • BFC (邊距重疊解決方案)面試常考,也容易混淆的題目

盒模型

基本概念

什麼是 CSS 盒模型?相信大部分人都能答出這個問題來,那就是 標準模型 + IE 模型

標準模型:

面試之CSS篇 - 邊距重疊與BFC

IE 模型

面試之CSS篇 - 邊距重疊與BFC

很明顯

  • 在 標準盒子模型中,widthheight 指的是內容區域的寬度和高度。增加內邊距、邊框和外邊距不會影響內容區域的尺寸,但是會增加元素框的總尺寸。
  • IE 盒子模型中,widthheight 指的是content+border+padding

CSS 如何設定這兩種模型

  • 標準模型:box-sizing: content-box;
  • IE 模型:box-sizing: border-box;

JS 如何設定盒模型對應的寬和高

  • dom.style.width/height : 只能取出內聯樣式的寬和高 eg: <div id="aa" style="width: 200px"></div>
  • dom.currentStyle.width/height 獲取即時計算的樣式,但是隻有 IE 支援,要想支援其他瀏覽器,可以通過下面的方式
  • window.getComputedStyle(dom).width: 相容性更好
  • dom.getBoundingClientRect().width/height: 這個較少用,主要是要來計算在頁面中的絕對位置

邊距重疊

什麼是邊距重疊呢?

邊界重疊是指兩個或多個盒子(可能相鄰也可能巢狀)的相鄰邊界(其間沒有任何非空內容、補白、邊框)重合在一起而形成一個單一邊界。

父子元素的邊界重疊

<style>
  .parent {
    background: #e7a1c5;
  }
  .parent .child {
    background: #c8cdf5;
    height: 100px;
    margin-top: 10px;
  }
</style>
<section class="parent">
  <article class="child"></article>
</section>
複製程式碼

以為期待的效果:

面試之CSS篇 - 邊距重疊與BFC

而實際上效果如下:

面試之CSS篇 - 邊距重疊與BFC

在這裡父元素的高度不是 110px,而是 100px,在這裡發生了高度坍塌。

原因是如果塊元素的 margin-top 與它的第一個子元素的 margin-top 之間沒有 borderpaddinginline contentclearance 來分隔,或者塊元素的 margin-bottom 與它的最後一個子元素的 margin-bottom 之間沒有 borderpaddinginline contentheightmin-heightmax-height 分隔,那麼外邊距會塌陷。子元素多餘的外邊距會被父元素的外邊距截斷。

兄弟元素的邊界重疊

<style>
  #margin {
    background: #e7a1c5;
    overflow: hidden;
    width: 300px;
  }
  #margin > p {
    background: #c8cdf5;
    margin: 20px auto 30px;
  }
</style>
<section id="margin">
  <p>1</p>
  <p>2</p>
  <p>3</p>
</section>
複製程式碼

面試之CSS篇 - 邊距重疊與BFC

可以看到 1 和 2,2 和 3 之間的間距不是 50px,發生了邊距重疊是取了它們之間的最大值 30px。

空元素的邊界重疊

假設有一個空元素,它有外邊距,但是沒有邊框或填充。在這種情況下,上外邊距與下外邊距就碰到了一起,它們會發生合併:

面試之CSS篇 - 邊距重疊與BFC

BFC

解決上述問題的其中一個辦法就是建立 BFC。BFC 的全稱為 Block Formatting Context,即塊級格式化上下文。

  • 處於同一個 BFC 中的元素相互影響,可能會發生 margin collapse;
  • BFC 在頁面上是一個獨立的容器,容器裡面的子元素不會影響到外面的元素,反之亦然;
  • 計算 BFC 的高度時,考慮 BFC 所包含的所有元素,包括浮動元素也參與計算;
  • 浮動盒的區域不會疊加到 BFC 上;

防止垂直 margin 重疊

父子元素的邊界重疊得解決方案: 在父元素上加上 overflow:hidden;使其成為 BFC。

.parent {
  background: #e7a1c5;
  overflow: hidden;
}
複製程式碼

面試之CSS篇 - 邊距重疊與BFC

兄弟元素的邊界重疊,在第二個子元素建立一個 BFC 上下文:

<section id="margin">
    <p>1</p>
    <div style="overflow:hidden;">
        <p>2</p>
    </div>
    <p>3</p>
</section>
複製程式碼

面試之CSS篇 - 邊距重疊與BFC

清除內部浮動

<style>
  #float {
    background: #fec68b;
  }
  #float .float {
    float: left;
  }
</style>
<section id="float">
  <div class="float">我是浮動元素</div>
</section>
複製程式碼

父元素#float 的高度為 0,解決方案為為父元素#float 建立 BFC,這樣浮動子元素的高度也會參與到父元素的高度計算:

#float {
  background: #fec68b;
  overflow: hidden; /*這裡也可以用float:left*/
}
複製程式碼

面試之CSS篇 - 邊距重疊與BFC

自適應兩欄佈局

<section id="layout">
  <style>
    #layout {
      background: red;
    }
    #layout .left {
      float: left;
      width: 100px;
      height: 100px;
      background: pink;
    }
    #layout .right {
      height: 110px;
      background: #ccc;
    }
  </style>
  <!--左邊寬度固定,右邊自適應-->
  <div class="left"></div>
  <div class="right"></div>
</section>
複製程式碼

在這裡設定右邊的高度高於左邊,可以看到左邊超出的部分跑到右邊去了,這是由於由於浮動框不在文件的普通流中,所以文件的普通流中的塊框表現得就像浮動框不存在一樣導致的。

面試之CSS篇 - 邊距重疊與BFC

解決方案為給右側元素建立一個 BFC,原理是 BFC 不會與 float 元素髮生重疊。

#layout .right {
  height: 110px;
  background: #ccc;
  overflow: auto;
}
複製程式碼

面試之CSS篇 - 邊距重疊與BFC

參考 邊距重疊與 BFC

相關文章