margin 是盒模型几个属性中一个非常特殊的属性。简单举几个例子:只有 margin 不显示当前元素背景,只有 margin 可以设置为负值,margin 和宽高支持 auto,以及 margin 具有非常奇怪的重叠特性。之前的博文中已经分别详细地介绍了和。本文将详细介绍外边距 margin 的几个重点部分,包括重叠、auto 和无效情况
【前提】
margin 重叠又叫 margin 合并,发生这种情况有两个前提
1、只发生在 block 元素上 (不包括 float、absolute、inline-block 元素)
2、只发生在垂直方向上 (不考虑 writing-mode)
【分类】
margin 重叠共包括以下 3 种情况
1、相邻的兄弟元素
- <style>
- p{
- line-height: 2em;
- margin:1em 0;
- background-color: lightblue;
- display:inline-block;
- width: 100%;
- }
- </style>
- <p>兄弟一</p>
- <p>兄弟二</p>
2、父级元素和第一个或最后一个子元素,父子级的 margin 重叠又叫 margin 传递
- <style>
- .box{
- background-color: pink;
- height:30px;
- }
- .inner{
- margin-top: 1em;
- background-color: lightblue;
- }
- </style>
- <div class="box">
- <div class="inner">子级</div>
- </div>
条件
相对比相邻兄弟元素 margin 重叠来说,父子级 margin 重叠需要满足以下几个条件 (以 margin-top 重叠为例):
a、父元素不是元素
b、父元素没有 padding-top 值
c、父元素没有 border-top 值
d、父元素和第一个子元素之间没有 inline 元素分隔
如果是父子级的 margin-bottom 重叠,第 d 条改为父元素和最后一个子元素之间没有 inline 元素分隔,以及还需要满足父元素没有 height、min-height、max-height 限制
3、空的 block 元素
- <style>
- .box{
- background-color: lightgreen;
- overflow: hidden;
- }
- .void{
- margin: 1em 0;
- }
- </style>
- </head>
- <body>
- <div class="box">
- <div class="void"></div>
- </div>
- 一行文字
从下面结果中,可以看出空 block 元素应该撑开父级 margin-top+margin-bottom 共 2em 的高度,但由于 margin 重叠,只有 1em
同样地,空 block 元素发生 margin 重叠也需要满足一些条件
a、元素没有 border 值
b、元素没有 padding 值
c、里面没有 inline 元素
d、没有 height 或 min-height
【规则】
两个正垂直外边距,浏览器取大值;如果垂直外边距都设置为负值,浏览器会选取两个外边距的绝对值的最大值;如果一个正外边距与一个负外边距合并,会从正外边距减去这个负外边距的绝对值
简单点说,就是正正取大值、正负值相加、负负最负值
【用途】
在网页布局中,因为 margin 重叠的原因,我们常常把 margin 作为一个 "问题样式" 而尽量少地使用它。但实际上,它是在很大的作用的
html 文档创建的初衷只是用来展示信息的。HTML 文档只使用默认样式的前提下,如果上下 margin 不发生重叠,则会出现以下几个问题:1、连续段落或列表之类,如果没有 margin 重叠,首尾项间距会和其他兄弟元素呈现 1:2 的关系,排版不自然;2、web 中任何地方嵌套或直接放入任何裸 div,都会影响原生的布局,与 web 设计原则相违背;3、遗落的空的任意多个 p 标签,会影响原来的阅读排版
所以,我们要善用重叠,可以在列表项中同时使用 margin-top 和 margin-bottom。这样,使页面结构更具有健壮性,最后一个元素移除或位置调换,都不会破坏原生的布局
只有 width/height 和 margin 可以设置 auto。关于 auto 的详细信息,已经在中详细介绍过。下面仅介绍关于 margin:auto 的部分
【为什么 margin:auto 无法实现垂直居中】
水平方向可以居中是因为块级元素的宽度默认是撑满父级元素的,如果给宽度设置一个固定值,而左右 margin 设置为 auto,则可以平分剩余空间
垂直方向不可以居中是因为块级元素的高度默认是内容高度,与父级元素的高度并没有直接的关系,而上下 margin 设置为 auto,则被重置为 0
【为什么图片使用 margin:auto 不能水平居中】
图片无法水平居中,类似于块级元素无法垂直居中。因为图片的宽度 width 默认是自身宽度,与父元素的宽度没有直接关系。左右 margin 设置为 auto,会被重置为 0
所以,图片要水平居中,需要设置为 display:block 元素
【实现垂直居中】
使用 margin:auto 实现垂直居中,有以下两种方法
1、使用 writing-mode:vertical-lr;
writing-mode 代表页面流方向,默认是水平方向。改为垂直方向后,可实现垂直居中,但水平不居中了
2、将元素变为绝对定位元素 (IE7 - 浏览器不支持)
将元素变为绝对定位元素后,设置 top:0;bottom:0;,使绝对定位元素与定位父级的高度有了直接的联系。再设置 margin:0 auto;,使 margin-top 和 margin-bottom 平分剩余空间,达到垂直居中的效果
1、行内元素垂直 margin 无效
因为行内元素垂直布局主要是通过行高 line-height 和垂直对齐 vertical-align 来影响的,垂直 margin 并不会影响它们,所以不会影响垂直布局。而在显示方式,margin 区域不会显示元素背景,所以也不会影响自身元素的显示,所以行内元素垂直 margin 无效
[注意] 不包括 inline-block 或设置 writing-mode 为 vertical-lr 的情况
2、某些表格类元素 margin 无效
不可设置 margin。对于 display 属性来说,display 为 table 相关类型 (不包括 table-caption、table、inline-table),margin 声明无效
- <thead>``<tbody>``<tfoot>``<tr>``<col>``<colgroup>``<td>``<th>
3、绝对定位元素非定位方向的 margin 值看似无效
绝对定位的 margin 值是一直有效的,只是因为绝对定位元素是脱离文档流的,与其他元素节点没有什么关系,所以看不出效果
4、BFC 造成的 margin 看似无效
左侧元素使用浮动,右侧元素使用 overflow-hidden 实现两栏自适应的布局时,右侧元素的 margin-left 值只有足够大,才能看到效果。这是因为 margin-left 是相对于父元素左侧,而不是图片右侧
5、内联特性导致的 margin 无效
一个 div 里面包着一张图片,当图片的 margin-top 小到一定值时,图片就不再接着向上移动了。这是因为图片是内联元素,它受制于内联元素 vertical-align 对齐特性的影响。默认基线对齐。以页面假想的大写 X 字符为例,X 是不会因为图片 margin-top 足够小而跑到父元素外面的,所以图片移动到一定位置就不再接着向上移动了
来源: