一、前言
在學習CSS時,遇到的很多問題都是和margin有關,這個小怪獸總是出其不意的讓我的界面排版變的混亂,還讓人摸不着頭腦,原因還是在於我對他的一些屬性沒有進行一個深入的了解,導致我在設計之初就忽略了一些潛在的bug。所以本文就margin屬性以及常見的問題做一個總結歸納。
二、什么是margin
CSS 邊距屬性定義元素周圍的空間。通過使用單獨的屬性,可以對上、右、下、左的外邊距進行設置。也可以使用簡寫的外邊距屬性同時改變所有的外邊距。——W3School
邊界,元素周圍生成額外的空白區。“空白區”通常是指其他元素不能出現且父元素背景可見的區域。——CSS權威指南
是不是看到以上的權威解釋還是不明所以?別急,我畫個圖你就明白了。
還不明白?那好,我給你舉個栗子,假設你住在一個別墅區,每棟別墅都是一個元素, 既然是別墅了那怎么着也得有個圍牆吧(當然也可以沒有,純粹取決於業主喜不喜歡)。圍牆就相當於上圖的border邊界(灰色區域),圍牆與房子(上圖的child即元素內容)之間的空間就是padding內邊距(黃色區域),而圍牆之外的空間就是外邊距margin了(紫色區域),你可以當做是別墅與別墅之間的空間距離。margin存在的目的就是控制元素之間的間隔使頁面排版更加的美觀整齊,但它不屬於元素的私有財產,在計算元素大小的時候可不要把margin算在內哦,畢竟你總不能把你家門口空氣算作你自己的吧,那太霸道啦!看到這里你是不是對margin的作用范圍有了大致的了解了,如果還不清楚,請繼續往下看呀~
三、margin的特性
1、margin始終透明。這個特性其實可以這么理解,margin存在的目的就是為了隔開不同的元素使布局更加的美觀,如果margin不是透明的就無法讓不同的元素產生間隙達到隔開的目的還會影響其他布局,所以margin必須是透明的。
2、簡寫特性。margin屬性可以設置4個值,分別是margin:top right bottom left;(可以按照順時針的方式記憶,即:上右下左。順序不能亂),這四個值也可以單獨設置,即:margin-top、margin-bottom、margin-right、margin-left。除了可以單獨設置之外,margin還可以進行簡寫(如非必要,不建議使用第三種簡寫),基本如下:
- margin只有一個值,表示top、right、bottom、left都是同一個值。例如:margin:10px等價於margin:10px 10px 10px 10px;
- margin只有兩個值,第一值表示top、bottom的值,第二個值表示right、left的值。例如:margin:10px 20px等價於margin:10px 20px 10px 20px;
- margin只有三個值,第一個值表示top的值,第二個值表示right、left的值,第三個值表示bottom的值。例如:margin:10px 20px 30px等價於margin:10px 20px 30px 20px;
3、垂直方向外邊距合並。塊級元素的上外邊距(margin-top)與下外邊距(margin-bottom)有時會合並為一個外邊距,這樣的現象稱為“margin合並”。只發生在與當前文檔流方向相垂直的方向上,並且只能是塊級元素。
四、margin合並的三種場景(縱向重疊)
1、相鄰兄弟元素margin合並。這是margin合並中最常見、最基本的。例如:
p { margin: 1em 0; background-color: pink; } <p>第一行</p> <p>第二行</p>
效果圖:
第一行和第二行的間距還是1em,因為第一行的margin-bottom和第二行的margin-top合並在了一起,並非上下相加。
2、父級和第一個/最后一個子元素合並。

1 <style> 2 .grandfather { 3 border: 2px solid red; 4 width: 300px; 5 height: 300px; 6 } 7 8 .father { 9 width: 200px; 10 height: 200px; 11 background-color: yellow; 12 } 13 14 .son { 15 margin: 2em 0; 16 background-color: pink; 17 } 18 </style> 19 20 <body> 21 <div class="grandfather"> 22 <div class="father"> 23 <div class="son">this is son</div> 24 </div> 25 </div>
效果圖:
當給子元素添加外邊距之后,父元素和子元素的上外邊距(margin-top)發生了合並,導致父元素上外邊距等同於變成了子元素的上外邊距(合並的外邊距值若都為正,則外邊距取兩者的最大值)造成了視覺上的父元素塌陷但實際父元素的上外邊距的值並未改變。如何阻止這里margin合並的發生呢?
對於margin-top合並,可以進行如下操作(滿足一個條件即可):
- 父級元素設置為塊狀格式化上下文元素(設置BFC),比如:給父級元素添加overflow:hidden;(推薦)
- 父元素設置border-top值;
- 父元素設置padding-top的值;
- 父元素和第一個子元素之間添加內聯元素進行分隔
對於margin-bottom合並,可以進行如下操作(滿足一個條件即可):
- 父級元素設置為塊狀格式化上下文元素
- 父級元素設置border-bottom值
- 父級元素設置padding-bottom值
- 父級元素和最后一個子元素之間添加內聯元素進行分隔
- 父級設計height、min-height或max-height
上面例子中在.father中添加overflow:hidden效果如下:
3、空塊級元素的margin合並。例如:
.father { overflow: hidden; } .son { margin: 1em 0; } <div class="father"> <div class="son"></div> </div>
效果圖:
此時,.father所在的這個父級<div>元素高度僅僅是1em,因為.son這個空<div>元素的margin-top和margin-bottom合並在了一起。
五、margin負值問題
- margin-top和margin-left負值,元素向上、向左移動
- margin-right負值,右側元素左移,自身不受影響
- margin-bottom負值,下方元素上移,自身不受影響
案列展示:
(1)margin-top為負值
(2)margin-left為負值
(3)margin-right為負值
(4)margin-bottom為負值
六、margin無效的問題
1、display:inline的非替換元素的垂直margin無效,對於內聯替換元素垂直margin有效,並且沒有margin合並的問題,所以圖片永遠不會發生margin合並。
2、表格中的<tr>和<td>元素或者設置display計算值是table-cell或table-row的元素的margin都是無效的。但是如果計算值是table-caption、table或者inline-table則沒有此問題,可以通過margin控制外間距,甚至::first-letter偽元素也可以解析margin。
3、margin合並的時候,更改margin值可能是沒有效果的。以父子margin重疊為例,假設父元素設置有margin-top:50px,則此時子元素設置margin-top:30px就沒有任何效果表現,除非大小比50px大,或者是負值。
4、絕對定位元素非定位方向的margin值“無效”。因為絕對定位元素的渲染是獨立的,普通元素和兄弟元素是互相關聯的,但是絕對定位元素由於獨立渲染無法和兄弟元素產生聯系,因此margin無法影響兄弟元素定位,所以看上去就是無效的。
5、定高容器的子元素的margin-bottom或者寬度定死的子元素的margin-right的定位“失效”。這個現象的本質和和上面絕對定位元素非對立方margin值“無效”類似。原因在於,若想使用margin屬性改變自身的位置,必須是和當前元素定位方向一樣的margin屬性才可以,否則,margin只能影響后面的元素或者父元素。
好了,總結了這么多,我想你應該對margin屬性不陌生了吧,如果對你有幫助,就點個贊吧~
參考文檔
https://www.cnblogs.com/zhangmingze/articles/4664074.html
https://blog.csdn.net/weixin_39855431/article/details/79929135
http://www.nowamagic.net/librarys/veda/detail/1608
https://blog.csdn.net/xun__xing/article/details/107334925
https://www.cnblogs.com/jjucap/p/5339725.html