分享

css margin bug:div子元素外边距margin跑到父级元素上的问题产生原理及解决

 Dead n Gone 2014-11-09

今天在知道上看见一网友问的问题,大概是他网页中有两个父子关系的 div,父级 div 没有任何外边距,而子级 div 顶部有有外 10px 边距,结果这 10px 的顶部外边距没按他的期望出现在父、子两个 div 之间,而是跑到父级 div 的顶部去了。

 

该网友想知道产生这个结果的原理,知道原文:

http://zhidao.baidu.com/question/332708289.html

(知道回答的时候我没试 Opear,以为只有 IE6 出这个问题)

 

这个问题我曾经遇到过多次,出现问题的情况:

·IE6、Opear 下出现、其他版本 IE 没装,Firefox 和 Chrome 没装,不确定是否有相同问题,以前遇着这个问题有否试过其他浏览器也记不清楚了,不过看样子都会有,有兴趣的朋友自己测试。

·只是有时候出现这个问题,说明需要一定的条件才会出现,我只测试到当父级元素没有宽度时这个问题问发生:

-------------------------------------------

<!Doctype html>
<html>

<head>
 <style>
  body{
   margin:0;
   font-size:12px;
   line-height:18px;
  }
  
  div{
   width:600px;/*IE下删除这个父元素的宽度就会发生,Opear下有没这个宽度都会发生*/
   background:#ccc;
  }
  
  p{
   margin:10px 0;
  }
 </style>
</head>

<body>

 <div>
  <p>
AAA任何通过使用百度而搜索链接到的第三方网页均系他人制作或提供,您可能从该第三方网页上获得资讯及享用服务,百度对其合法性概不负责,亦不承担任何法律责任。
  </p>
  <p>

BBB您应该对使用搜索引擎的结果自行承担风险。百度不做任何形式的保证:不保证搜索结果满足您的要求,不保证搜索服务不中断,不保证搜索结果的安全性、正确性、及时性、合法性。因网络状况、通讯线路、第三方网站等任何原因而导致您不能正常使用百度,百度不承担任何法律责任。
  </p>
 </div>

</body>

</html>

-------------------------------------------

由于提问的网友父级 div 赋予了 950px 的宽度,说明还有其他不明诱因情况下也会出现,这个有志气的朋友探索研究后还望告知。

 

导致这个错误的原因:

此错误是由 margin 外边距垂直合并引起的,如下面 html 在 css 中给 p 定义上下各 10px 外边距:

-----html-----

<div>

<p>AAA</p>

<p>BBB</p>

</div>

-----css-----

p{margin:10px 0;}

 

理论上正确的结果是 AAA 的顶部离父级 div 有 10px 外边距,BBB 的底部离父级 div 也有 10px 距离,AAA、BBB 之间有 20px 距离

(AAA 底部 10px + BBB 顶部 10px = 20px);

 

但按这个方式处理出现了一个问题,AAA、BBB 之间 20px 的外边距影响了排版上的美观,于是浏览器解析过程中就自动将 AAA 的 10px 底边距和 BBB 的 10px 顶边距强制叠加到一起,使其只有 10px 距离;

 

margin外边距强制合并发生的条件:

1. 水平 margin 不会合并。

2. 两个上下渲染相邻(不一定是兄弟节点)的块状元素在正常页面流情况下会发生 margin 合并。

3. 浮动元素不会和任何元素(包括子孙节点)发生 margin 合并。

4. overflow = visible 的元素不和任何元素发生 margin 合并。

5. 绝对定位的元素不和任何元素发生 margin 合并。

6. inline-block 的元素不和任何元素发生 margin 合并。

7. 设置 clear 属性的元素不和任何元素发生 margin 合并。

8. 根元素不和任何元素发生 margin 合并。

9. 父节点和第一个子节点发生 margin-top 合并。

10. 如果最后一个子节点没有 border 以及 padding ,则和其父节点发生 margin-bottom 合并。

 

提问题那个网友显然是中了上面第 9 条的招:

由于他的父级 div 没有外边距,而子 div 有外边距,所以浏览器强制合并外边距后,距离依然为 10px (0+10px=10px);但是 bug 出现了,本该出现在父子之间的 10px 距离跑到了父级 div 的外面,而父子之间反而没有距离了。

 

由此我们可以推断出:

浏览器在处理这两个 div 合并他们垂直外边距时的顺序是:从后面的子级开始去合并到父级的,即:BBB 顶部外边距去叠加重合到 AAA 底部的外边距上,这时父级 AAA  底部外边距为 0,BBB 往 AAA 的边界外面挤了,产生了这个问题。

 

此 bug 的解决办法:

父元素加上垂直方向的 padding 内边距,有内边距就会隔开里面那个 div 的垂直方向外边距,强制其无法产生垂直外边距自动合并。

加 border 也可以解决,只要满足上面 1-10 的条件或者其他办法都能避免这个问题。

 

文字啰嗦,不明白的看图:

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多