深刻理解css中的margin屬性(最新瀏覽器支持)

本文啓發於博客園一篇2016年的「深刻理解css中的margin屬性」文章,根據當前瀏覽器(
chrome 71.0.3578.98(正式版本) (64 位)),加上本身的理解,每一個例子都是親測過css

這篇博文主要分爲如下幾個部分:html

margin--基礎知識
margin--在同級元素(非父子關係)之間應用
margin--在父元素和子元素之間應用(重點)
margin--margin值的單位爲%時的幾種狀況chrome

第一部分:margin--基礎知識

  要介紹margin的基礎知識,咱們不可迴避地要談到css盒子模型(Box Model),通常而言,css盒子模型是用來設計和佈局的。它本質上是一個盒子,包括:外邊距(margin)、邊框(border)、內邊距(padding)以及最中間的內容(content)。下圖即爲盒子模型(這裏只談W3C規範的標準盒模型,而不談IE5和IE6在怪異模式中使用的非標準的盒子模型):瀏覽器

clipboard.png

   咱們要介紹的margin在最外層,由於margin(外邊距)必定是透明的,因此它能夠用來使得不一樣的盒子之間留有必定的間隙從而達到佈局美觀等效果。從上面的盒子模型中咱們能夠看到,margin在四周均存在,咱們可使用margin-top、margin-right、margin-bottom、margin-left分別設置這四個方向的margin值。(注:因爲這部分知識較爲基礎,因此我再也不在這部分不作更多介紹)佈局

第二部分:margin--在同級元素(非父子關係)之間應用

  這一部分主要介紹水平方向和豎直方向的外邊距的合併問題。spa

 ####(1)水平方向的外邊距合併
  兩個水平方向的盒子相遇,那麼最終二者之間的距離爲左邊盒子的右外邊距和右邊盒子的作外邊距之和。設計

例1:代碼以下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>水平方向的兩個盒子</title>
    <style>
        *{
            margin:0;
            padding:0;
            border:0;
        }
        body{
            font-size: 0;
        }
        .left{
            width: 100px;
            height: 100px;
            background: red;
            display: inline-block;
            margin-right: 50px;
            font-size: 20px;
        }
        .right{
            width: 100px;
            height: 100px;
            background: yellow;
            display: inline-block;
            margin-left: 50px;
            font-size: 20px;
        }
    </style>
</head>
<body>
    <div class="left">寬爲100px,右邊距爲50px</div>
    <div class="right">寬爲100px,左邊距爲50px</div>
</body>
</html>

效果以下:code

clipboard.png

這時二者之間的距離恰好爲100px。htm

補充說明:你們能夠看到,爲了使得兩個div(塊狀元素)脫離正常的文檔流我使用了display:inline-block;屬性,另外,我還把body的font-size設置爲0,這樣能夠解決inline-block自身的問題(若是不清楚這裏的描述能夠看個人博文《理解與應用css中的display屬性》,這篇文章介紹了inline-block存在的問題),不然兩個div的舉例會大於100px。固然使用float也可使得兩個div出如今同一行中。blog

####(2)豎直方向的外邊距合併
  兩個豎直方向的盒子相遇時,其豎直方向的距離等於上方盒子的下外邊距和下方盒子的上外邊距中較大的一個。

  例2:代碼以下:

 `
<head>

<meta charset="UTF-8">
<title>水平方向的兩個盒子</title>
<style>

    .top{
        width: 100px;
        height: 100px;
        margin-bottom: 100px;
        background: red;
    }
    .bottom{
        width: 100px;
        height: 100px;
        margin-top: 50px;
        background: green;
    }
</style>

</head>
<body>

<div class="top">高爲100px,下邊距爲100px</div>
<div class="bottom">高爲100px,上邊距爲50px</div>

</body>
</html>

  效果以下:


![clipboard.png](/img/bVbnQFi)


**這時咱們肉眼均可以觀察出來,二者豎直方向的舉例大約爲100px(實際就是100px)而非100+50=150px;這正是由於兩個豎直方向的盒子相遇時,其豎直方向的距離等於上方盒子的下外邊距和下方盒子的上外邊距中較大的一個。**

  另一個有趣的例子就是:假設有一個元素同時設置了margin-top和margin-bottom,可是內容爲空,那麼這兩個margin值也會疊加,值爲二者最大的一個,它相似與豎直方向上兩個盒子margin值的疊加。代碼以下:

<!DOCTYPE html>
<html lang="en">
<head>

<meta charset="UTF-8">
<title>水平方向的兩個盒子</title>
<style>

    .top{
        width: 500px;
        height: 100px;
        background: red;
    }
    .middle{
        margin-top: 100px;
        margin-bottom:50px;
    }
    .footer{
        width: 500px;
        height: 100px;
        background: green;
    }

</style>

</head>
<body>

<div class="top">上面的div,高100px</div>
<div class="middle"></div>
<div class="footer">下面的div,高100px</div>

</body>
</html>

  最終的效果以下:


![clipboard.png](/img/bVbnQFs)


  **咱們發現這時在上面的div和在下面的div之間的舉例並非100+50=150px,而是二者中的最大者,即100px。**

  
  那麼W3C爲何會設定這樣的標準而不設定和水平方向同樣的標準呢?即margin值的疊加,實際上這也是有必定的道理的。好比咱們須要設計一個由若干個段落構成的一個頁面。咱們須要設置margin-top和margin-bottom使得第一段和頁面的最上方有一段距離,使得最後一段和最下方有一段距離。下面是不疊加和疊加的效果圖:

![clipboard.png](/img/bVbnQFM)

咱們能夠看到左邊的頁面沒有重疊,那麼兩個段落之間的舉例就是最上方的兩倍間距了,而右邊的頁面發生了重疊,則全部的間距都是相等的。或許這就是這樣設定標準的目的吧,誰知道呢?

###第三部分:margin--在父元素和子元素之間應用(重點)
    第二部分介紹了同級元素之間使用margin,而這一部分將要介紹最有意思的父元素和子元素之間margin的應用。這一部分,咱們一樣從兩個方面來討論。一方面是子元素設置水平方向上的margin值,另外一方面是子元素設置豎直方向的margin值。

####(1)在子元素中設置水平方向的margin值
  咱們能夠設置margin-left來控制子元素的左邊框和父元素的左邊框之間的舉例。
  例3:

<!DOCTYPE html>
<html lang="en">
<head>

<meta charset="UTF-8">
<title>margin</title>
<style>
    *{padding:0; margin:0; border:0;}
    .father{
        width: 500px;
        height: 500px;
        background: red;
    }
    .son{
        width: 100px;
        height: 100px;
        background: green;
        margin-left: 100px;
    }
</style>

</head>
<body>

<div class="father">
    <div class="son">寬度爲100px,margin-left爲100px。</div>
</div>

</body>
</html>

我將子元素的margin-left設置爲了100px;效果以下:

![clipboard.png](/img/bVbnQFU)


即子元素的左邊框和父元素的左邊框之間的距離爲100px。與在同級元素之間設置margin不一樣,由於同級元素之間的margin不會考慮到padding,可是在父元素和子元素就不一樣了,那麼若是父元素中若是有padding,效果會是什麼樣的呢?請看下面一個例子:

例4:下面咱們在上面例子的基礎上給父元素添加padding值。

<!DOCTYPE html>
<html lang="en">
<head>

<meta charset="UTF-8">
<title>margin</title>
<style>
    *{padding:0; margin:0; border:0;}
    .father{
        width: 500px;
        height: 500px;
        padding:100px;
        background: red;
    }
    .son{
        width: 100px;
        height: 100px;
        background: green;
        margin-left: 100px;
    }
</style>

</head>
<body>

<div class="father">
    <div class="son">寬度爲100px,margin-left爲100px。</div>
</div>

</body>
</html>
 `
上面的代碼給父元素添加了100px的padding值,效果以下:
clipboard.png

咱們能夠看到子元素舉例上方的距離爲100px,由於子元素必定是在父元素的content的部分的,這點毫無疑問。

可是通過測量能夠發現子元素的左邊框距離父元素的左邊框之間的距離爲200px,由於其中還有100px的左padding值,前面的例子由於我沒有設置padding值,因此沒有觀察出來,所以這就說明了在子元素中設置margin-left,其值其實是子元素的左邊框距離父元素左padding內側的距離。

 例5:margin-right的使用和margin-left的使用是類似的,我在這裏只舉一個例子。

  這個例子在子元素中設置了margin-right值,以下所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>margin</title>
    <style>
        *{padding:0; margin:0; border:0;}
        .father{
            width: 500px;
            height: 500px;
            padding:100px;
            background: red;
        }
        .son{
            float: right;
            width: 100px;
            height: 100px;
            background: green;
            margin-right: 100px;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="son">寬度爲100px,margin-right爲100px。</div>
    </div>
</body>
</html>

這個例子與例4的區別僅在與子元素的位置不一樣。效果以下:

clipboard.png

經過這個例子能夠說明margin-right的值是子元素的右邊框和父元素的右padding內側的距離。只是前面的幾個例子我沒有使用padding,因此沒法觀察出來。

(2)在子元素中設置豎直方向的margin值

 按照前面的經驗,理論上來講,咱們一樣能夠經過設置margin-top的值使得子元素的上邊框和父元素的上padding的內側留有必定的距離。那麼咱們就試試吧!
  例6:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>margin</title>
    <style>
        *{padding:0; margin:0; border:0;}
        .father{
            width: 500px;
            height: 500px;
            background: red;
        }
        .son{
            width: 100px;
            height: 100px;
            background: green;
            margin-top: 100px;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="son">高度爲100px,margin-top爲100px。</div>
    </div>
</body>
</html>

  這個例子我設置了margin-top爲100px,效果以下:

這並非咱們想要的效果啊,咱們但願子元素的上部距離父元素的上部爲100px,但是咱們看到的倒是父元素的上部距離瀏覽器頁面的上部有100px的距離,這是爲何呢?哪裏出現問題了呢?

clipboard.png

  實際上這是由於當父元素沒有設置padding值以及border值時,出現了一個bug--父元素的上方與子元素的上方徹底重合在了一塊兒,沒法分開。因此纔會致使上述這種父元素和子元素同時向下的狀況。

對於這種問題解決方法有下面幾種:

方法一:給父元素添加padding-top值
方法二:給父元素添加border值
方法三:給父元素添加屬性overflow:hidden,或者overflow:auto;
方法四:給父元素或者子元素聲明浮動float
方法五:使父元素或子元素聲明爲絕對定位:position:absolute;

方法一:基於例6,在父元素的css代碼中添加padding-top:1px;方法的惟一缺點就是增長了1px的偏差。

方法二:基於例6,在父元素的css代碼中添加border-top:1px solid transparent;一樣達到了效果, 缺點同方法一。

方法三:基於例6,在父元素的css代碼中添加overflow:hidden;
一樣達到了效果,而且沒有任何偏差的存在。堪稱perfect!!!!

方法四:給父元素或者子元素聲明float;基於例6,在子元素css代碼添加float:left;或者在父元素css代碼添加float:left;均達到效果,優勢:沒有像素的偏差。 缺點:float有時是沒必要要的。

方法五:給父元素或者子元素添加position:absolute;屬性。 一樣達到效果。
優勢:同方法四。 且只要咱們不使用top和left也不會有任何影響,因此這也是一種不錯的方法。

上述方法3、4、五實際上都是去除子元素margin穿透父容器的方法,能夠歸類爲bfc法,本質相同。

第四部分:margin值的單位爲%時的幾種狀況

 以前我舉例子時使用margin,它的值都是以px爲單位的,這個理解起來沒有問題。可是若是margin值是以%爲單位呢?實際上這時候百分比(%)是相對於該元素的父元素(容器),對於同級元素和父子元素都是如此。(再次感謝 博友@小精靈Pawn 提供的建議!!基於此建議補充這部份內容) 可是在同級元素中使用豎直方向的margin時會出現意想不到的結果,下面舉例說明。

(1)同級元素在水平方向使用值爲%的margin

  例7:

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>margin</title>
    <style>
        *{
            margin:0;
            padding:0;
        }
        .first{
            float: left;
            width: 200px;
            height: 200px;
            background: green;
        }
        .second{
            float: left;
            width: 200px;
            height: 200px;
            background: red;
            margin-left: 20%;
        }
    </style>
</head>
<body>
    <div class="first">寬爲200,無margin</div>
    <div class="second">寬爲200,margin-left爲20%;</div>
</body>
</html>

這個例子中,設置兩個元素向左浮動,以便於觀察二者水平方向的margin。其中左邊div無margin,右邊div的margin-left爲20%,效果以下:

clipboard.png

從效果圖能夠看出兩個div之間的間距始終爲父元素(這裏右邊div的父元素即爲body,其寬度爲瀏覽器寬度)的20%。

(2)同級元素在豎直方向使用值爲%的margin

   根據例7的啓發,咱們能夠猜測,若是在豎直方向上使用margin,且值的單位爲%,那麼最終二者之間的距離將是父元素(上例中爲body)的百分數。那麼到底是不是這樣呢?看下面的例子。

例8

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>margin</title>
    <style>
        *{
            margin:0;
            padding:0;
        }
        .first{
            width: 200px;
            height: 200px;
            background: green;
        }
        .second{
            width: 200px;
            height: 200px;
            background: red;
            margin-top: 10%;
        }
    </style>
</head>
<body>
    <div class="first">高爲200,無margin</div>
    <div class="second">高爲200,margin-top爲20%;</div>
</body>
</html>

這裏設置上面的div無margin,下面的div的margin-top爲10。
咱們發現,當我在縮小瀏覽器的高度時,豎直方向上的間距並無縮小!!! 而當我縮小瀏覽器的寬度時,豎直方向上的距離縮小了!!!

這就說明:統計元素之間在豎直方向上使用margin,當值的單位爲%時,它是相對於父元素的寬度。

  那麼這裏爲何不是如咱們所但願的那樣相對於瀏覽器的高度呢?知乎上有大神是這樣解釋的(原文地址:https://www.zhihu.com/questio...):

clipboard.png

(3)父子元素使用值爲%的margin

  對於父子元素,若是在子元素中使用單位爲%margin,那麼這個margin值是相對於父元素的寬度和高度的。

例9 代碼以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin:0;
            padding:0;
        }
        .father{
            width: 500px;
            height: 300px;
            background: red;
            overflow: hidden;
        }
        .son{
            width: 100px;
            height: 100px;
            background: green;
            margin-top: 20%;
            margin-left: 20%;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="son"></div>
    </div>
</body>
</html>

在這個例子中,我設置了margin-left的值爲20%,margin-top的值爲20%,父元素的width爲500px,父元素的height爲300px。下面看看效果吧。

從上圖能夠看出子元素的margin-top值最終一樣是
clipboard.png

相關文章
相關標籤/搜索