深入理解css中的margin屬性


轉載自  http://www.cnblogs.com/zhuzhenwei918/p/6124263.html

深入理解css中的margin屬性

  之前我一直認為margin屬性是一個非常簡單的屬性,但是最近做項目時遇到了一些問題,才發現margin屬性還是有一些“坑”的,下面我會介紹margin的基本知識以及那些“坑”。這篇博文主要分為以下幾個部分:

  

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

  要介紹margin的基礎知識,我們不可回避地要談到css盒子模型(Box Model),一般而言,css盒子模型是用來設計和布局的。它本質上是一個盒子,包括:外邊距(margin)、邊框(border)、內邊距(padding)以及最中間的內容(content)。下圖即為盒子模型(這里只談W3C規范的標准盒模型,而不談IE5和IE6在怪異模式中使用的非標准的盒子模型):

 

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

 

 

 

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

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

 (1)水平方向的外邊距合並

     兩個水平方向的盒子相遇,那么最終兩者之間的距離為左邊盒子的右外邊距和右邊盒子的做外邊距之和。

     例1:

       代碼如下:

    

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<! 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 >

  效果如下:

這時兩者之間的距離剛好為100px。

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

 

  (2)豎直方向的外邊距合並

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

  例2:

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<! DOCTYPE  html>
< html  lang="en">
< head >
     < meta  charset="UTF-8">
     < title >水平方向的兩個盒子</ title >
     < style >
         *{
             margin:0;
             padding:0;
             border:0;
         }
         .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 >

  效果如下:

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

  

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<! DOCTYPE  html>
< html  lang="en">
< head >
     < meta  charset="UTF-8">
     < title >水平方向的兩個盒子</ title >
     < style >
         *{
             margin:0;
             padding:0;
         }
 
         .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 >

  最終的效果如下:

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

  

  那么W3C為什么會設定這樣的標准而不設定和水平方向一樣的標准呢?即margin值的疊加,實際上這也是有一定的道理的。比如我們需要設計一個由若干個段落構成的一個頁面。我們需要設置margin-top和margin-bottom使得第一段和頁面的最上方有一段距離,使得最后一段和最下方有一段距離。下面是不疊加和疊加的效果圖:

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

 

 

第三部分:margin--在父元素和子元素之間應用(重點

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

  (1)在子元素中設置水平方向的margin值

    我們可以設置margin-left來控制子元素的左邊框和父元素的左邊框之間的舉例。

    例3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<! 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;效果如下:

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

  

  例4:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<! 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值,效果如下:

我們可以看到子元素舉例上方的距離為100px,因為子元素一定是在父元素的content的部分的,這點毫無疑問。

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

 

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<! 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的區別僅在與子元素的位置不同。效果如下:

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

 

 

 

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

    按照前面的經驗,理論上來說,我們同樣可以通過設置margin-top的值使得子元素的上邊框和父元素的上padding的內側留有一定的距離。那么我們就試試吧!

  例6:

        

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<! 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的距離,這是為什么呢?哪里出現問題了呢?

  

  實際上這是因為當父元素沒有設置padding值以及border值時,出現了一個bug--父元素的上方與子元素的上方完全重合在了一起,無法分開。所以才會導致上述這種父元素和子元素同時向下的情況。

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

  • 方法一:給父元素添加padding-top值
  • 方法二:給父元素添加border值
  • 方法三:給父元素添加屬性overflow:hidden;
  • 方法四:給父元素或者子元素聲明浮動float
  • 方法五:使父元素或子元素聲明為絕對定位:position:absolute;
  • 方法六:給父元素添加屬性 overflow:auto; positon:relative;(注:此方法為后續添加,感謝博友@小精靈Pawn提供此方法)

  方法一:基於例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也不會有任何影響,所以這也是一種不錯的方法。

(說明:博友 @laden666666 指出,上述方法三、四、五實際上都是去除子元素margin穿透父容器的方法,可以歸類為bfc法,本質相同。 在此表示感謝) 

      方法六:給父元素添加overflow:auto;和position:relative;同樣達到效果。

      此方法親測有效,是博友 @小精靈Pawn提供,在此表示感謝。

 

 

第四部分:margin值的單位為%時的幾種情況

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

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

  例7:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
< 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%,效果如下:

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

 

 

  

 

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

   根據例7的啟發,我們可以猜想,如果在豎直方向上使用margin,且值的單位為%,那么最終兩者之間的距離將是父元素(上例中為body)的百分數。那么究竟是不是這樣呢?看下面的例子。

例8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
< 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/question/20983035?rf=27109182):

 

 

 

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

    對於父子元素,如果在子元素中使用單位為%margin,那么這個margin值是相對於父元素的寬度和高度(注意:這時的確是相對於父元素的高度!)的。

        例9  

    代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<! 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值最終同樣是相對與父元素的寬度而非高度。


免責聲明!

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



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