你不知道的margin属性

目录
  1. 导读
  2. 垂直外边距合并问题
  3. margin是否对内联元素生效?
  4. 有关margin的常见bug
    1. IE6中浮动元素3px间隔Bug
    2. inline-block元素之间空白Bug
    3. IE6/7负margin隐藏Bug
    4. IE6/7下ul/ol标记消失bug
    5. IE6/7下margin与absolute元素重叠bug
    6. IE6/7/8下auto margin居中bug
    7. IE8下input[button | submit] 设置margin:0 auto无法居中
    8. IE8百分比padding垂直margin bug

导读

margin属性处于盒子模型的最外层, 用以隔开其他元素, 它可以依次设置4个长度值, 分别表示 “上 右 下 左” 的间距, 其中第1个和第3个值相对应, 第2个与第4个相对应, 如果省略前者, 后者将取与前者相同的数值. margin属性共存在以下 4 种表示方式:

  • margin: 10px 1rem 1em 5%; 共 4 个数值, 表示依次设置 上, 右, 下, 左的间距;
  • margin: 10px 1rem 1em; 共 3 个数值, 省略第4个值, 左间距将取右间距的值, 表示依次设置 上, 左右, 下的间距;
  • margin: 10px 1rem; 共 2 个数值, 省略第3,4个值, 左间距将取右间距的值, 下间距将取上间距的值, 表示依次设置 上下, 左右的间距;
  • margin: 10px; 共 1 个数值, 同时省略第2,3,4个值, 表示上下左右的间距均为10px;

若是块级元素, 借助 margin:0 auto; 即可实现水平居中.

看到这里, 你可能会觉得这些你都懂了, 这不要紧, 显然本文也不是为了科普margin的基础语法, 请往下看.

垂直外边距合并问题

别被上面这个名词给吓倒了, 简单地说, 外边距合并指的是, 当两个垂直外边距相遇时, 它们将形成一个外边距. 合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者. 你可以查看W3Shool CSS外边距合并了解这个基本知识.

实际工作中, 垂直外边距合并问题常见于第一个子元素的margin-top会顶开父元素与父元素相邻元素的间距, 而且只在标准浏览器下(FirfFox、Chrome、Opera、Sarfi)产生问题, IE下反而表现良好.

<style>
  .outer-box{
      margin-top:15px;
  }
  .inner-box{
      margin-top:30px;
  }
</style>
<div class="outer-box">
  <div class="inner-box">1234567890</div>
</div>

打开控制台, 你会发现内部div距离顶部的距离是30px, 而不是45px, 这是因为内部div与外部div的margin-top属性做了合并, 取两者中的最大值, 即 30px.

如果按照CSS规范, IE的“良好表现”其实是一个错误的表现, 因为IE的hasLayout渲染导致了这个“表现良好”的外观. 而其他标准浏览器则会表现出“有问题”的外观. 好了, 如果你读过了上面W3Shcool的CSS外边距合并的文章后, 就很容易讨论这个问题了. 这个问题发生的原因是根据规范, 一个盒子如果没有上补白(padding-top)和上边框(border-top), 那么这个盒子的上边距会和其内部文档流中的第一个子元素的上边距重叠.

基于此, 该问题便很好解决了, 给外部div设置一个透明的1像素的border-top即可.

.outer-box{
  margin-top:15px;
  border-top:1px solid transparent;
}

margin是否对内联元素生效?

margin也能用于内联元素, 这是规范所允许的, 但是margin-top和margin-bottom对内联元素(对行)的高度没有影响, 并且由于边界效果(margin效果)是透明的, 他也没有任何的视觉影响.

这是因为边界应用于内联元素时不改变元素的行高度,如果你要改变内联元素的行高即类似文本的行间距, 那么你只能使用这三个属性: line-height, fong-size, vertical-align. 请记住, 这个影响内联元素高度的是line-height而不是height, 因为内联元素是一行行的, 定一个height的话, 那这到底是整段inline元素的高呢? 还是inline元素一行的高呢? 这都说不准, 所以统一都给每行定一个高, 只能是line-height了.

margin-top/margin-bottom对内联元素没有实际效果, 不过margin-left/margin-right还是能够对内联元素产生影响的. 应用margin:10px 20px 30px 40px;, 左边这个css如果写在inline元素上, 他的效果大致是, 上下无效果, 左边离他相邻元素或者文本距离为40px, 右边离他相邻元素或者文本距离为20px.

有关margin的常见bug

下面罗列一下常见的有关margin的bug, 可能不全, 非常欢迎交流探讨, 请在回复中补充.

IE6中浮动元素3px间隔Bug

发生场景: 发生在一个元素浮动,然后一个不浮动的元素自然上浮与之靠近会出现的3px的bug.
解决方法: 右边元素也一起浮动; 或者为右边元素添加IE6 Hack “_margin-left:-3px;” 从而消除3px间距.
原因分析:IE6浏览器缺陷Bug.

inline-block元素之间空白Bug

发生场景: IE8+、Chrome、Firefox、Safari等浏览器下的效果, 两个inline-block的元素之间会存在一定的空白间距, 空白间距的宽度与父元素的font-size大小有关.

解决方法: 可以为inline-block元素设置为负的margin-left; 或父元素font-size设置为0, 子元素再重新设置回来, 如需兼容所有浏览器, 请参考 inline-block空白间距解决方案探讨.

原因分析: HTML 中的换行符、空格符、制表符等合并为空白符, 字体大小不为 0 的情况下, 空白符自然占据一定的宽度, 因此产生了元素间的空隙.

IE6/7负margin隐藏Bug

发生场景: 当给一个有hasLayout的父元素内的非hasLayout元素设置负margin时, 超出父元素部分不可见.
解决方法: 去掉父元素的hasLayout; 或者赋hasLayout给子元素,并添加position:relative;
原理分析: IE6/7独有的hasLayout产生问题.

IE6/7下ul/ol标记消失bug

发生场合: 当ul/ol触发了haslayout并且是在ul/ol上写margin-left, 前面默认的ul/ol标记会消失.
解决方法: 给li设置margin-left, 而不是给ul/ol设置margin-left.
原因分析:IE6/7浏览器Bug.

IE6/7下margin与absolute元素重叠bug

发生场景: 双栏自适应布局中, 左侧元素absolute绝对定位, 右侧的margin撑开距离定位. 在IE6/7下左侧应用了absolute属性的块级元素与右边的自适应的文字内容重叠.
解决方法: 把左侧块级元素更改为内联元素, 比如把div更换为span.
原因分析: 这是由于IE6-7浏览器将inline水平标签元素和block水平的标签元素没有加以区分一视同仁渲染了. 属于IE6-7浏览器渲染Bug.

IE6/7/8下auto margin居中bug

发生场景: 给block元素设置margin auto无法居中
解决方法: 出现这种bug的原因通常是没有Doctype, 然后触发了ie的quirks mode, 加上Doctype声明就可以了. 在《打败IE的葵花宝典》里给出的方法是给block元素添加一个width能够解决, 但据测试, 加with此种方法是无效的, 如果没有Doctype即使给元素添加width也无法让block元素居中.
原因分析: 缺少Doctype声明.

IE8下input[button | submit] 设置margin:0 auto无法居中

发生场景: ie8下, 如果给像button这样的标签(如button input[type=”button”] input[type=”submit”])设置{ display: block; margin:0 auto; }如果不设置宽度的话无法居中.
解决方法: 可以给为input加上宽度.
原因分析: IE8浏览器Bug.

IE8百分比padding垂直margin bug

发生场景: 当父元素设置了百分比的padding, 子元素有垂直的margin的时候, 就好像父元素被设置了margin一样.
解决方法: 给父元素加一个overflow:hidden/auto。
原因分析: IE8浏览器Bug.


本文就讨论这么多内容,大家有什么问题或好的想法欢迎在下方参与留言和评论.

本文作者: louis

本文链接: http://louiszhai.github.io/2016/03/23/css-margin/

参考文章

Fork me on GitHub