最近一直纠结于浮动和非浮动元素相邻时候的奇怪表现,按照我的理解,浮动元素浮动后就脱离了普通文档流,相邻的非浮动元素就会忽略浮动元素本来应该占有的那部分空间。
按照我之前的理解,那么我认为如果一个元素A浮动了,那么相邻的非浮动元素B一定会被A覆盖在下面了,但是实际情况中我有两个现象不解
现象1、为什么在IE6下面,浮动元素不能覆盖在相邻的非浮动元素之上,而是和相邻的非浮动元素一起左右排列?
现象2、为什么在IE8 firefox chrome safari下,浮动元素覆盖着相邻的非浮动元素,但是非浮动元素包含的文字却不被覆盖而是围绕着浮动元素?并且如果非浮动元素的垂直高度上超过了浮动元素高度后的文字又从容器最左侧出现了而不是围绕着浮动元素了,这到底是为什么呢?
下面的例子可以很好的说明上面的2点情况具体是什么样子
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>浮动与hasLayout研究 文字围绕</title>
<style>
*{
margin:0;
padding:0;
font-size:12px;
}
.box{
width:300px;
overflow:auto;
}
.leftbox{
background:#CCC;
width:100px;
height:30px;
float:left;
*margin-right:-3px; /*针对IE6 浮动元素水平右外边距移动-3px 即可解决*/
}
.textbox{
width:200px;
background:#FFCCCC;
}
</style>
</head>
<body>
<div class="box">
<div class="leftbox">浮动元素</div><p class="textbox">文本文本文本文本文本文本文本文本文本文本文本文本文文本文本文本文本文本文本文本文本文本文本文本文本本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本</p>
</div>
</body>
</html>
这是在火狐下的表现(IE8 chrome safari也是一样的效果)
这是在IE6下的表现
经过我这几天的研究,我已经可以解释上面2点奇异现象,下面我来一一解剖。
1、为什么IE6下非浮动元素不会被浮动元素覆盖?
大家看看我上面的CSS部分
.textbox{
width:200px;
background:#FFCCCC;
}
我给非浮动元素textbox定义了固定的宽度,这一行为触发了元素在IE下特有的hasLayout,也就是说让textbox元素拥有了布局。
说通俗一点吧,IE6 下当元素没有拥有布局的情况下,它的表现和其他浏览器是一致的,之所以我看到的表现不同了,那是因为该元素被触发了hasLayout。
在IE6下80%以上的怪异表现和BUG均是它引起的,关于hasLayout我有其他文章进行过研究 hasLayout 介绍,以及其触发条件
关于上面第一点的表现,就是因为textbox定义了固定宽度,而这个CSS设置会触发它的hasLayout,而当元素拥有布局后,在IE6下它不再忽略浮动元素应该占有的空间,所以它不会被覆盖,而是排列在浮动元素的右侧。
如何让上面的代码表现的和IE8等浏览器一样呢?很简单,解除非浮动元素的布局,也就是不要触发它的hasLayout,是什么引起的我们就删除什么,把width:200px;删除,我们就可以看到所有浏览器都一致的表现,那就是非浮动元素被浮动元素覆盖在下面。
IE6下很多BUG都是可以通过触发元素的hasLayout来解决的,但是也有需要避免触发的时候,这个例子就是需要避免触发hasLayout。
2、为什么在IE8等浏览器下,虽然非浮动元素按照我们的理解,它是被浮动元素覆盖了,但是它包含的文字为什么不会被覆盖,而是围绕浮动元素呢?
按照我们之前的理解,元素浮动后,非浮动元素会忽略浮动元素本应该占有的空间,所以我们肯定费解为什么文字不被覆盖,好像还给浮动元素留了空间,并没有忽略啊,这怎么回事?
从看书到实际操作,再到看书,来回折腾了几次我终于明白了原因。
浮动元素所说的不占据空间,到底是什么空间?关于空间,我的理解有2种:
(1)行框空间
一个行框自身的宽度是由其包含的行内框的尺寸决定的,而行内框的尺寸无疑就是因为其包含的文字等决定的。行框最大的宽是父容器的宽度。
比如上面代码中的P元素,它是个块元素,它如果没有被定义固定宽度,默认宽度应该是100%,也就是父容器的宽度。如果我们删除上面代码
.textbox{
width:200px;
background:#FFCCCC;
}
里面的固定宽度 width:200px; 这时候浮动元素不会占据块的空间,所以P元素就是100%的父容器宽度 300px,但是浮动元素会占据另外的空间,这就是我现在说的行框空间。
我的意思是:浮动元素不会占据相邻非浮动元素的块空间,但是它会占据非浮动元素内的行框空间。比如行框由于众多文字的撑开已经达到了最大宽度,也就是父元素P的宽度300px,但是行框空间被占据了100px(浮动元素的宽度),行框就被缩短了100px,只剩下了200px了。
所以我们视觉上看到的是浮动元素覆盖了P元素,因为它不占据块空间;但同时它又占据了块元素内的行框空间, 所以行框里面的行内框以及文字,他们只能被迫从浮动元素旁边排列,直到浮动元素结束的地方才从新获得了本来大小的行框空间,也就是经过30px高度后,行框宽度又恢复到了300px,这30px高度就是浮动元素的高度,它占据了行框100px*30px的这么一块空间。
同理,我即便不删除 width:200px; 这个固定宽度,那么P元素的宽度就是200px,它包含的行框被占据了100px,行框宽只有100px。
(2)文档空间
经过上面的解释,我相信第二种空间也不需要再多解释什么了,上面说的块空间,其实就是文档空间。
浮动元素浮动后脱离文档流,不占据文档空间,所以它不会占据P元素的空间。
经过第二点现象的解释后,这里回头看下第一点也就是IE6现象的原因,我们可以得出,在定义了非浮动元素的固定宽度后,就触发了hasLayout,使得textbox拥有布局,那么这时候浮动元素可不仅仅占据行框空间,它还要占据文档空间,所以我们才会看到在IE6下,非浮动元素没有被覆盖。
相信到这里,大家都明白了为什么在IE8 firefox等浏览器下会有 浮动覆盖非浮动,非浮动的文字环绕浮动元素 这个现象了吧
而IE6下的怪异表现,大家也都知道是什么引起的了吧,如果大家有什么不同的见解或者要补充的,欢迎给我回复。
之后又写了一篇 纠结的 hasLayout与overflow:hidden — 清除浮动之谜 欢迎大家批评指正