{备注:关于margin的相关问题有待验证,今天精力有限,做下备注,以后完善}
研究后发现,IE下许多BUG都与IE私有属性haslayout有关,那么接下来我们总结下IE中因为haslayout导致的bug。关于haslayout属性我在之前文章里做过总结,希望大家批评指正
【目录】
1、浮动元素与普通元素之间产生3px bug
2、块级元素与浮动元素不会重叠
3、浮动闭合元素
4、ie下margin不塌陷
5、ie下margin-left/right失效
下面依次解析
1、浮动元素与普通元素之间产生3px bug
我是浮动元素我是后面的文字,用来测试3px的bug
IE6下会出现3px的距离
解决方式:加一个ie6的hack:*margin-right:-3px;
注意:不只是文字,ie6的浮动元素也会和内联元素产生3px的margin值,解决方案相同
2、块级元素与浮动元素不会重叠
先上代码看下效果(分别打开chrome与IE浏览器对比下)
运行后可以明显地发现IE下块级元素跟浮动元素不能重叠css1
为什么会发生这种情况呢?是因为我在块级元素上设置了高度。激活了IE下的haslayout属性,于是把该元素以BFC类似的方式进行渲染。而BFC官方布局规则里说过,BFC的区域不会与float box重叠(可以解决浮动造成的重叠覆盖相关问题)
关于IE中块级元素与浮动元素并排显示,这里我分开情况介绍下:
①要使其他浏览器也显示同样效果(这里我用chrome检验),也是并排显示
因为IE激活了haslayout属性,与BFC渲染方式相同,所以这里我们想办法激活BFC
BFC布局规则第四条:BFC的区域不会与float box重叠(所以可以解决浮动造成的重叠覆盖问题)
元素产生BFC的原因{
根元素
float属性不为none
position为absolute或fixed
display为inline-block, table-cell, table-caption, flex, inline-flex
overflow不为visible
}
我们任意选取上面一种原因加给块级元素,比如加上overflow:hidden;于是元素产生了BFC效果导致元素收缩,不再占据浮动元素位置
②解决IE并排问题,使其和其他浏览器渲染出相同效果,即块级元素与浮动元素重叠
这里先来分析下:
IE之所以没有重叠,是因为块级元素的宽高触发了IE的haslayout属性,产生于类似BFC渲染效果(BFC规定BFC的区域不会与float box重叠,所以这里我们再创建一个独立的独立容器BFC,即可在效果上实现重叠)
所以我们接下来要利用BFC布局规则,再创建一个单独的BFC(之前说过BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素;外面的元素也不会影响到容器里面的子元素;)
(分析完了,下面来看案例)
我是浮动元素我是浮动元素后面的块级元素
可以明显地发现IE下块级元素跟浮动元素不能重叠
为什么会发生这种情况呢?是因为我在块级元素上设置了高度。激活了IE下的haslayout属性。于是把它以BFC类似的方式进行渲染。
解决方式:在块级元素外再包裹一层DIV。并且把内部DIV的background的属性写在外层DIV上
我是浮动元素我是浮动元素后面的块级元素
3、浮动闭合元素
这个问题其实很多人会遇到,我之前也提到过,只是可能叫法不同
我浮动啦!
IE似乎妥妥的。其实很多情况下,我们想要的是ie这种效果
在ie中,一个浮动元素总是隶属于包含它的容器。是因为.test设置了宽度,激活了haslayout属性。而在非ie浏览器中,我们想要获得这种效果一般是在父盒子上加一个:after的伪对象来清除浮动,或者设置overflow:hidden来触发BFC(BFC规定计算高度时加上浮动元素高度)
插入提一下闭合浮动的普遍做法:为需要闭合浮动的父元素加入clearfix的类
.clearfix:after{ content:".";/*加一段内容*/ display:block;/*让生成的元素以块级元素显示,占满剩余空间*/ height:0;/*避免生成的内容破坏原有布局高度*/ clear:both;/*清除浮动*/ visibility:hidden;/*让生成的内容不可见*/ } .clearfix{zoom:1;/*为IE6,7的兼容性设置*/}
4、ie下margin不塌陷
先看个例子(分别用IE与chrome打开查看效果)
我浮动啦!测试margin-top在ie下是否塌陷
float是浮动元素,它脱离了文档流,所以第二个DIV的margin-top相对的是其上级.test作用的。但我们只是对第二个DIV设置margin-top。结果在chrome下,怎么连float也“产生了margin-top”呢?
对比IE和chrome下的效果,是不是觉得IE下的解析会比较合理呢?
【margin塌陷(margin collapsing)】
但是,别忘了影响margin-top/bottom的一个重要规则——margin塌陷(margin collapsing)
【注意:】水平margin不会合并;
提到了margin塌陷,我们来看看margin垂直方向上塌陷的一些条件:
①父节点和第一个子节点发生margin-top合并
②两个上下渲染相邻(不一定是兄弟节点)的块状元素在正常页面流情况下会发生 margin 合并;
③浮动元素不会和任何元素(包括子孙节点)发生 margin 合并;
④overflow!=visible的元素不和任何元素发生margin合并;
⑤绝对定位的元素不和任何元素发生margin合并;
⑥inline-block 的元素不和任何元素发生margin合并;
⑦设置 clear 属性的元素不和任何元素发生margin合并;
⑧根元素不和任何元素发生margin合并;
⑨如果最后一个子节点没有border以及padding,则和其父节点发生margin-bottom合并
在现代浏览器下.test块的高度并没有被子元素第二个DIV的margin-top撑开。反而自身拥有了30px的margin-top
而浮动块尽管脱离了文档流,但还是受其父级限制的(这跟absolute定位的元素层受限于其定义为relative的父级一样)。所以float还是包含在test之中,这样在chrome下看起来浮动块也拥有margin-top,而事实上是因为test高度不撑开的结果
这么说,chrome并没有错咯,那么IE下又是怎么避开margin塌陷的呢?
问题就出在浮动上面,在ie下,元素浮动将触发其haslayout。就是这个原因,使得在ie下意外(意外?)的就避开了margin塌陷。但是根据规范,一个盒子如果没有上补白(padding-top)和上边框(border-top),那么这个盒子的上边距会和其内部文档流中的第一个子元素的上边距重叠。
(接下来{}内是深入讲解,推荐看下)
{ 其实再说了白点就是:父元素的第一个子元素的上边距margin-top如果碰不到有效的border或者padding.就会不断一层一层的找自己“领导”(父元素,祖先元素)的麻烦。对于垂直外边距合并的解决方案上面已经解释了,为父元素例子中的middle元素增加一个border-top或者padding-top即可解决这个问题。
一般说来这个问题解释到这里,大多数文章就不会再深入下去了,但作为一名实战开发者,最求的是知其然知其所以然,原本使用margin-top就是为了与父元素隔开距离,而按照你这么一个解法,其实是一种“修复”,为了“弥补修复”这个父子垂直外边距合并这个CSS规范“Bug”,而强制在父元素上使用border-top和padding-top,不舒服,也不容易记住,下次再发生这样的情况还是会忘记这条准则,而且在页面设计稿里如果不需要border-top加个上边框,这么一加反而画蛇添足,为以后修改留下隐患。
为什么一定要用border-top,padding-top去为了这么一个所谓的标准规范而多写这么一行代码呢?答案你可以参考另外一篇文章用Margin还是用Padding里找到答案。
(1)用Margin还是用Padding
何时应当使用margin:
需要在border外侧添加空白时。
空白处不需要背景(色)时。
上下相连的两个盒子之间的空白,需要相互抵消时。如15px + 20px的margin,将得到20px的空白。
何时应当时用padding:
需要在border内测添加空白时。
空白处需要背景(色)时。
上下相连的两个盒子之间的空白,希望等于两者之和时。
(2)个人认为:
margin是用来隔开元素与元素的间距;padding是用来隔开元素与内容的间隔;
margin用于布局分开元素使元素与元素互不相干;
padding用于元素与内容之间的间隔,让内容(文字)与(包裹)元素之间有一段“呼吸距离”
}
END探讨结束
(新问题)但是奇怪的是,如果给.test加上border,chrome的渲染情况就跟ie一样了,float没有拥有与第二个DIV相同的margin-top值。而是紧贴.test的顶部。这个问题的原因还需要研究一下
【研究结果】
查阅文档后得知,父与子合并margin时,父子之间不能出现间隙(比如:border或者padding引起的间隙)。而加上border后 相当于两个div之间出现的boder导致的间隙,从而导致margin不能合并
5、ie下margin-left/right失效
测试失效的margin-left
分析可以发现,IE下我们为子DIV设置的margin失效了
为什么会发生这种情况?
同样是是因为子DIV设置了高度,激活了haslayout属性
解决办法:不为子DIV设置高度,或者把父盒子的haslayout也激活
.
BUG列表:(以下内容均本人亲测)
问题 | 浏览器 | DEMO | 解决办法 | |
1 | input[button | submit]未居中 | IE8 | bug | fixed | 添加width |
2 | body{overflow:hidden;}没有去掉滚动条 | IE6/7 | bug | fixed | 改成html{overflow:hidden;} |
3 | 拥有hasLayout的标签有高度 | IE6/7 | bug | fixed | 添加_overflow:hidden;*height:0 |
4 | form>[hasLayout]元素有margin-left时,子元素中的[input | textarea] 出现2×margin-left | IE6/7 | bug | fixed | form > [hasLayout 元素]{margin-left:宽度;} form div{*margin-left:宽度÷2;} |
5 | 当子元素有position:relative的时候,父元素设置overflow:[hidden|auto]相当于给子元素设置了position:visible; | IE6/7 | bug | fixed | 给父元素设置position:relative; |
6 | 列表中混乱的浮动:在list中浮动图片时,图片出现溢出正常位置;或没有list-style | IE8 | bug | fixed | 用背景图片替换list-style |
7 | th 不会自动继承上级元素的 text-align | IE8 | bug | fixed | 给th添加text-align:inherit; |
8 | 样式(包括link/style/@import(link)) 最多允许个为是:32 | IE6-8 | ─ 常识 | 99.99%的情况下,不会遇到 |
9 | PNG图片中的颜色和背景颜色的值相同,但显示不同 | IE6-7 | bug | fixed | 利用pngcrush去除图片中的 Gamma profiles |
10 | margin:0 auto; 不能让block元素水平居中 | IE6-8 | bug | fixed | 给block元素添加一个width |
11 | 使用伪类 :first-line | :first-letter, 属性的值中出现!important 会使属性失效 | IE8 | bug | fixed | !important is evil, don’t use it anymore |
12 | :first-letter 失效 | IE6 | bug | fixed | 把 :first-letter 移到离{}最近的地方,如 h1, p:first-letter{},而非 p:first-letter h1{} |
13 | Position:absolute元素中,a display:block, 在非:hover时只有文本可点击 | IE6/7 | bug | fixed | 给a添加background, 如果背景透明,使用background:url(‘任何页面中已经缓存的文件链接’),不推荐background:url(#)[官方的解决方法],因为会增加一下HTTP请求 |
14 | dt, dd, li 背景失效 | IE6 | bug | fixed | dt, dd, li{position:relative;} |
15 | 元素的样式在启用javascript的情况下显示了样式 | IE6-8 | bug | fixed | 利用js给添加display:none; |
16 | li内元素偏离 baseline 向下拉 | IE8/9 | bug | fixed | 给li设置display:inline 或 float:[方向] |
17 | 列表中li的list-style不显示 | IE6/7 | bug | fixed | 给li添加margin-left,留空间来显示(不要加在ul上) |
18 | 图片不能垂直居中 | IE6/7 | bug/fixed | 添加一个空标签,并赋给”Layout”, 比如display:inline-block; |
19 | 不能自定义指针样式 | IE6-8 | bug | fixed | 给指针文件设置绝对路径 |
20 | 高度超过height定义的高 | IE6 | bug/fixed | 添加_overflow:hidden;(推荐)或者_font-size:0; |
21 | 宽度超过width定义的宽 | IE6 | bug/fixed | 添加_overflow:hidden; |
22 | 双倍边距 | IE6 | ─ 常识 | 添加display:inline到float元素中 |
23 | margin负值隐藏:hasLayout的父元素内的非hasLayout元素,使用负边距时,超出父元素部分不可见 | IE6/7 | bug/fixed | 去掉父元素的hasLayout;或者赋hasLayout给子元素,并添加position:relative; |
24 | 给两个浮动元素的某中一个的文字设定为斜体,另一个元素下拉在有斜体文字元素的下面 | IE6 | bug/fixed | 给有斜体文字的元素添加overflow:hidden; |
25 | 3px 间隔:在float元素后的元素,会有3px间隔 | IE6 | bug/fixed | 因为是确切的3px,所以,用“暴力破解”吧,比如_margin-left:-3px;或者也设置float |
26 | text-align 影响块级元素 | IE6/7 | bug/fixed | 整理你的float;或者分开设置text-align |
.