Margin會重疊,你造嗎

NancyJY發表於2019-05-06

之所以要專門寫一篇文章去解釋margin重疊,一是因為前面的文章裡有提到過,怕有些童鞋不瞭解;二是要寫的內容不是三言兩語就能說清楚的。

在講重疊之前,我們先來了解一下margin這個屬性。

一. margin 基礎講解

這個屬性呢,太常見,我就大概講講,有幾點大家注意一下就好。

margin, 實為margin-left, margin-right, margin-top, margin-bottom的一個簡寫,這些子屬性分別用來設定box的左 / 右 / 上 / 下外邊距的寬度,它們的具體用法如下:

屬性名: margin-left / margin-right / margin-top / margin-bottom
值: <length> | <percentage> | inherit
初始值: 0
繼承性: 無
應用物件:所有dom元素,除了display為table-row-group,table-row, table-column-group, table-column, table-header-group, table-footer-group, table-cell
百分比: 參考containing block的寬度
計算值(computed value,參考第4條):開發人員指定的百分比值 或 一個絕對長度

有一些使用細節需要說明一下:

  • margin-top和margin-bottom在inline box(看第18條)上沒有任何效果。
  • 屬性值設為百分比時,參考物件為containing block的寬度,即使是margin-top,margin-bottom也是醬紫的
  • margin設為一個值時,表明四個子屬性均為此值;設為兩個值時,表明margin-top和margin-bottom將為第一個值,margin-left和margin-right將為第二個值;設為三個值,表明margin-top取第一個值,margin-left和margin-right取第二個值,margin-bottom取第三個值;設為四個值,則按照top, right, bottom, left的順序從第一個值開始設定。例如:
margin:20px;  等同於 所有邊均為20px

margin:10px 20px; 等同於 margin-top & margin-bottom為10px, margin-left & margin-right為20px

margin:10px 20px 30px; 等同於 margin-top為10px, margin-left & margin-right為20px, margin-bottom為30px

margin:10px 20px 30px 40px; 等同於 margin-top為10px,margin-right為20px,margin-bottom為30px,margin-left為40px複製程式碼

嗯哼~蠻簡單的~~那就來點複雜的吧!

二. margin 重疊 詳解

何為margin重疊?兩個或多個box的相鄰margin合在一起,成為一個margin。其實就是兩個margin重疊在一塊,那麼呈現出來的效果當然是一個的咯。

如何才能產生這種效果呢?

首先,你得保證用的是垂直方向的margin(margin-top & margin-bottom)。你要是用margin-left和margin-right,試一百次都不會出現!

其次,應用物件要選好。不是所有box都可以!(突然覺得css裡的規則一套一套的,水好深~~)

最後,重疊的環境要準備好。即使物件選好了,重疊也不是百分百就有,只有滿足特定的條件才會產生。

重疊物件

在我說出之前,大家可以先想想哪些物件會有margin重疊。

我們可以試試排除法。CSS中的box無非就四種:float box,absolute positioned box,inline-level box, block-level box。

看過前面的定位文章的童鞋應該知道,float box和absolute positioned box都會脫離正常流而自成一條流,流與流之間是各玩各的,互不干擾,那麼我們可以先排除這兩種。而inline-level box在渲染過程中會參與inline formatting context,這個上下文中的box不會發生margin重疊。那麼剩下的只有block-level box。

那麼,所有的block-level box都會發生重疊嗎?

是的,但是——要排除root box(第28條)

現在,我們大致知道重疊物件會是兩個block-level box(不包括root box)。這只是一個初篩條件,這兩個重疊物件還必須同屬一個block formatting context,具體為什麼呢,看看之前介紹bfc的文章就明白了。

重疊環境

對於一個符合條件的box而言,以下任何一種情況都會發生重疊:

  1. top margin 與 它的第一個處於普通流中的孩子的top margin
  2. height 為auto,它的bottom margin 與 它的最後一個處於普通流中的孩子的bottom margin
  3. bottom margin 與 它的下一個處於普通流中的兄弟的top margin
  4. overflow為visible(即該box不會建立bfc), min-height 的computed value(第四條)為0,height的computed value為0或auto,無孩子box,它的top margin與bottom margin

特例:overflow不為visible的block-level box的margin不會與它的任何在普通流中的孩子發生margin 重疊,但可與處在同一bfc的兄弟box發現margin 重疊。

我們來看看示例:

例1:父box與第一個子孩子box

<!DOCTYPE>
<html>
  <head>
      <style>
          .parent{
              margin-top:20px;
              margin-bottom:10px;
              background-color: #e6e96e;
          }
          .child{
              background-color: aquamarine;
          }
          .first{
            margin-top:30px;
            margin-bottom:30px;
          }
      </style>
  </head>
  <body>
    <div class='parent'>
        <div class='child first'>haha</div>       
    </div>
 </body>
</html>複製程式碼

chrome瀏覽器顯示:

Margin會重疊,你造嗎
Margin會重疊,你造嗎

很明顯,兩者margin發生重疊。

例2:box自身的top margin與bottom margin發生重疊 && 兄弟box之間margin重疊 && overflow不為visible的box不與孩子box發生margin重疊

<!DOCTYPE>
<html>
  <head>
      <style>
          .parent{
              width:500px;
              min-height: 0;
              height:auto;
              margin-top:20px;
              margin-bottom:10px;
              background-color: #e6e96e;
          }
          .parent-second{
              overflow:hidden;
          }
          .child{
              background-color: aquamarine;
          }
          .first-child{
            margin-top:30px;
            margin-bottom:30px;
          }
          .second-child{
              width:200px;
              margin-top:60px;
              margin-bottom:60px;
          }
      </style>
  </head>
  <body>
    <div class='parent'>
    </div>
    <div class='parent parent-second'>
            <div class='child first-child'>haha in second div</div>
            <div class='child second-child'>lala in second div</div> 
    </div>
 </body>
</html>複製程式碼

chrom顯示如下:

Margin會重疊,你造嗎

我們看第一個 div.parent ,它的top margin與bottom margin發生重疊,這個重疊結果又與div.parent.second-parent的top margin發生重疊,所以頁面最上方的空白處margin只有20px,這個數值可以通過檢視div.parent.second-parent的margin得到(下圖的橙色部分)。

Margin會重疊,你造嗎

由上圖,我們也可以看到,div.parent.second-parent並未與自己的第一個孩子box發生margin 重疊。

重疊margin計算

假設第一個box的top margin值為A,它的第一個子孩子的top margin值為B,兩者margin重疊,重疊結果會按如下規則計算:

A,B均為正值,則取max(A, B)
A為負值,B為正值,則為B-|A|
A,B均為負值,則取0-max(|A|,|B|)

來個例子

為了更好的展示重疊結果,將html元素的top margin設為100px(注:html元素產生的是root box,不會發生margin重疊),同時去掉瀏覽器為body設定的margin。

<!DOCTYPE>
<html>
  <head>
      <style>
          html{
            margin-top:100px;
          }
          *{
            margin-top:0;
            margin-bottom:0;
          }
          .parent{
              width:100px;
              height:100px;
              background-color: #e6e96e;
          }
          .child{
              width:100%;
              height:100%;
              background-color: aquamarine;
          }
      </style>
  </head>
  <body>
    <div class='parent'>
        <div class='child'>haha</div>       
    </div>
 </body>
</html>複製程式碼

chrome展示如下:

Margin會重疊,你造嗎

例3:A為負值,B為正值

為div.parent及div.child加上margin-top

          .parent{
              width:100px;
              height:100px;
              margin-top:-60px;
              background-color: #e6e96e;
          }
          .child{
              width:100%;
              height:100%;
              margin-top:10px;
              background-color: aquamarine;
          }複製程式碼

chrome裡顯示如下:

Margin會重疊,你造嗎

用inspect方式檢視margin的範圍:

Margin會重疊,你造嗎

可以看到,重疊margin值為html元素所設margin值的一半,即50px。它背後的運算過程是:10-|-60| = -50

例4:A, B均為負值

為兩個div加上margin-top

          .parent{
              width:100px;
              height:100px;
              margin-top:-10px;
              background-color: #e6e96e;
          }
          .child{
              width:100%;
              height:100%;
              margin-top:-50px;
              background-color: aquamarine;
          }複製程式碼

chrome顯示如下:

Margin會重疊,你造嗎

再檢視下margin範圍

Margin會重疊,你造嗎

margin重疊的結果依然為50px,但背後的運算卻不同,0 - max(|-10|, |-50|) = 0-50 = -50

小結:只有垂直margin才可重疊,且參與的物件為同一個bfc的block-level box;重疊只有滿足特定的條件才會發生;重疊的計算因margin值的正負情況而有所不同。


相關文章