margin 详解

Margin

垂直外边距合并问题

  • 问题的原因:元素一个盒子如果没有padding-topborder-top,那么这个盒子的margin-top就会和内部文档流中的第一个子元素的margin-top重叠。
    针对inline元素,margin只影响左右,上下无效。

  • 用Margin还是用Padding

    1. 何时应当使用margin:
      需要在border外侧添加空白时。
      空白处不需要背景(色)时。
      上下相连的两个盒子之间的空白,需要相互抵消时。如15px + 20px的margin,将得到20px的空白。
    2. 何时应当时用padding:
      需要在border内测添加空白时。
      空白处需要背景(色)时。
      上下相连的两个盒子之间的空白,希望等于两者之和时。如15px + 20px的padding,将得到35px的空白。

注:只有普通文档流中块元素的垂直外边距才会发生外边距合并。行内框(inline,inline-block)、浮动框或绝对定位之间的外边距不会合并。

行(inline)元素

普通行内元素只有margin-left(right)生效。

注:任何使其脱离文档流(float,absolute,fixed),都会使inline元素具备block的特性。如:可设置宽高,margin。

负margin

特性

  1. 盒子最后的显示大小等于盒子的border+padding+正margin,而负margin不会影响其大小。
  2. margin为负且盒子static时:
    • 若属性为top、left,盒子将被拉进指定的方向;
    • 若属性为bottom、right,将后续的元素拖拉进来,覆盖本来的元素。
  3. 若width没有被设置,设定负margin-left/right会将元素拖向对应的方向,并增加宽度,此时的margin的作用就像padding一样

科普

  1. 负margin是绝对标准的CSS
    W3C甚至标注过:对于margin属性来说,负值是被允许的。
  2. 负margin不是一种hack方法
    千真万确,不能因为缺乏对负margin的理解,或者因为它长得像hack,就认为它是一种hack方法。除非你是用来修复自己在其他地方造成的错误。
  3. 不脱离文档流
    不使用float的话,负margin元素是不会破坏页面的文档流。所以如果你使用负margin上移一个元素,所有跟随的元素都会被上移。
  4. 完全兼容
    所有现代浏览器都完全支持负margin(IE6在大多数情况下也支持)。
  5. 浮动会影响负margin的使用
    负margin不是你每天都用的CSS属性,应用时应小心谨慎。

用途

  1. 负margin在Tab选项卡中的应用
  2. 负margin负位移技术应用
  3. 利用负margin制作鳞片式导航
  4. 利用负margin制作自适应左右布局
  5. 左右固定,中间自适应(双飞翼)
  6. 去除列表右边框
  7. 多列等高

BUG处理

文字和链接的问题
当浮动元素使用负margin时,在一些旧的浏览器中可能会出现问题,问题现象包括:

  1. 链接无法点击;
  2. 文字难以选中;
  3. 失去焦点后,tab任何链接都会消失;
  • 解决方法:给元素添加position:relative,便能正常运行!

图片被截断
IE6,有时候会发现重叠和浮动的元素中内容会被突然截断。

  • 解决方法:同样,给浮动元素加上position:relative,一切将会恢复正常。

margin常见BUG

  1. IE6中双边距Bug
    发生场合:当给父元素内第一个浮动元素设置margin-left(元素float:left)或margin-right(元素float:right)时margin加倍。

    • 解决方法:是给浮动元素加上display:inline;CSS属性;或者用padding-left代替margin-left。
    • 原理分析:块级对象默认的display属性值是block,当设置了浮动的同时,还设置了它的外边距就会出现这种情况。也许你会问:“为什么之后的对象和第一个对象之间就不存在双倍边距的Bug”?因为浮动都有其相对应的对象,只有相对于其父对象的浮动对象才会出现这样的问题。第一个对象是相对父对象的,而之后对象是相对第一个对象的,所以之后对象在设置后不会出现问题。为什么display:inline可以解决这个双边距bug,首先是inline元素或inline-block元素是不存在双边距问题的。然后,float:left等浮动属性可以让inline元素haslayout,会让inline元素表现得跟inline-block元素的特性一样,支持高宽,垂直margin和padding等,所以div class的所有样式可以用在这个display inline的元素上。
  2. IE6中浮动元素3px间隔Bug
    发生场合:发生在一个元素浮动,然后一个不浮动的元素自然上浮与之靠近会出现的3px的bug。

    • 解决方法:右边元素也一起浮动;或者为右边元素添加IE6 Hack _margin-left:-3px;从而消除3px间距。
    • 原理分析:IE6浏览器缺陷Bug。
  3. IE6/7负margin隐藏Bug
    发生场合:当给一个有hasLayout的父元素内的非hasLayout元素设置负margin时,超出父元素部分不可见。

    • 解决方法:去掉父元素的hasLayout;或者赋hasLayout给子元素,并添加position:relative;
    • 原理分析:IE6/7独有的hasLayout产生问题。
  4. IE6/7下ul/ol标记消失bug
    发生场合:当ul/ol触发了haslayout并且是在ul/ol上写margin-left,前面默认的ul/ol标记会消失。

    • 解决方法:给li设置margin-left,而不是给ul/ol设置margin-left。
    • 原理分析:IE6/7浏览器Bug
  5. IE6/7下margin与absolute元素重叠bug
    发生场合:双栏自适应布局中,左侧元素absolute绝对定位,右侧的margin撑开距离定位。在IE6/7下左侧应用了absolute属性的块级元素与右边的自适应的文字内容重叠。

    • 解决方法:把左侧块级元素更改为内联元素,比如把div更换为span。
    • 原理分析:这是由于IE6/IE7浏览器将inline水平标签元素和block水平的标签元素没有加以区分一视同仁渲染了。属于IE6/7浏览器渲染Bug。
  6. IE6/7/8下auto margin居中bug
    发生场合:给block元素设置margin auto无法居中

    • 解决方法:出现这种bug的原因通常是没有Doctype,然后触发了ie的quirks mode,加上Doctype声明就可以了。在《打败IE的葵花宝典》里给出的方法是给block元素添加一个width能够解决,但根据本人亲测,加with此种方法是无效的,如果没有Doctype即使给元素添加width也无法让block元素居中。
    • 原理分析:缺少Doctype声明。
  7. IE8下input[button | submit] 设置margin:auto无法居中
    发生场合:ie8下,如果给像button这样的标签(如button input[type=”button”] input[type=”submit”])设置{ display: block; margin:0 auto; }如果不设置宽度的话无法居中。

    • 解决方法:可以给为input加上宽度
    • 原理分析:IE8浏览器Bug。
  8. IE8百分比padding垂直margin bug
    发生场合:当父元素设置了百分比的padding,子元素有垂直的margin的时候,就好像父元素被设置了margin一样。

    • 解决方法:给父元素加一个overflow:hidden/auto。
    • 原理分析:IE8浏览器Bug。

文章参考