CSS中浮动的主要目的有两种,一是为了实现文字绕排图片的效果,而是为了创建多栏布局。不得不说浮动浮动和清除是用来组织页面布局的一柄利剑,这柄剑的剑刃就是 float 和 clear属性。稍有不慎,剑走偏锋,页面就会变得满目疮痍,只有洞悉背后的玄机,方能游刃有余。
大家都知道浮动元素会脱离常规文档流,原来紧跟其后的元素就会在空间允许的情况下,向上提升到与浮动元素平起平坐。下面举例说明浮动布局以及清除浮动主要剑法。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>清除浮动</title>
<style type="text/css">
*{margin: 0;padding: 0;}
#wrapper{margin:10px;border:3px solid;}
p{border:1px solid red;}
/*img{float: left;}*/
</style>
</head>
<body>
<div id="wrapper">
<p>工欲善其事必先利其器,首先你会要用豆瓣,那里可以找到很多装逼者,共同学习,共同进步,豆瓣是个好东西,装逼必备啊。</p>
<img src="test1.jpg" />
<p>世界上总是有那么群爱装b的人,所以才有这篇不完全装b手册,为什么不完全呢?因为装的艺术是要表现在你生活的方方面面的.</p>
<p>唐代非著名诗人章碣曾很感慨地说“刘项原来不读书”,如果能做到刘邦、项羽这么牛b的人,是不需要靠读书来装的,但一个社会同时只能容纳一个这种牛人,不可能实现大家共同装b的愿望,不利于和谐社会的建立,所以这里不推荐。</p>
</div>
</body>
</html>
原始的页面如下图所示,页面由三个段落和一个img构成,为了方便查看,这里给父包围元素和段落添加了一个边框,由于p是块状元素,所以段落显示在图片下方。
现在将图片设置为向左浮动
img{float: left;}
可以看到图片下方的段落文字环绕图片排列。这里还可以得出一个结论,浮动的元素对其前面的同胞元素是没有影响的,不像绝对定位那样,如果left和top值设置的不合适会遮蔽前面的元素。现在如果我们不想让最后一段文字环绕图片,该怎么做呢?这时就要用到clear属性了。clear取值为下面三种
clear:left | right | both
为了清除图片的左浮动对后面同胞元素的影像,需要在受影响的后面的同胞元素上添加clear样式。
#wrapper p:last-of-type{clear: left;}//仅作演示用,未考虑老旧浏览器的兼容性
当然这里clear取值为both也能清除左浮动的影响。
现在我们看到最后的段落不再环绕图片了而是显示在图片下方。目前为止,上文已经介绍了float可clear的用法。所以是不是已经讲完了,该下班了!
Hold on,高潮才刚刚开始,现在我们做一个小测试,把最后一段文字的p标签移出来放在外包围div标签的下方,并且别忘了把前面清除浮动的css语句删除还原。html代码变成下面这样:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>清除浮动</title>
<style type="text/css">
*{margin: 0;padding: 0;}
#wrapper{margin:10px;border:3px solid;}
p{border:1px solid red;}
img{float: left;}
</style>
</head>
<body>
<div id="wrapper">
<p>工欲善其事必先利其器,首先你会要用豆瓣,那里可以找到很多装逼者,共同学习,共同进步,豆瓣是个好东西,装逼必备啊。</p>
<img src="test1.jpg" />
<p>世界上总是有那么群爱装b的人,所以才有这篇不完全装b手册,为什么不完全呢?因为装的艺术是要表现在你生活的方方面面的.</p>
</div>
<p>唐代非著名诗人章碣曾很感慨地说“刘项原来不读书”,如果能做到刘邦、项羽这么牛b的人,是不需要靠读书来装的,但一个社会同时只能容纳一个这种牛人,不可能实现大家共同装b的愿望,不利于和谐社会的建立,所以这里不推荐。</p>
</body>
</html>
完成操作以后,页面变成上面的挫样,仔细观察会发现,外包围的div元素没能包裹住图片元素,这种情况也被一些人叫做父元素高度塌陷。原因是浮动元素脱离了文档流,其父元素也看不到它了,因而也不会包围它。这种情况一般并不是我们想要的,下面向大家传授几种让父包裹元素重新包围住子元素的剑法。
- 方法一:设置父包裹元素overflow:hidden
<style type="text/css">
*{margin: 0;padding: 0;}
#wrapper{margin:10px;border:3px solid; overflow: hidden;}
p{border:1px solid red;}
img{float: left;}
</style>
现在我们看到最后一段文字已经跑到上一个div的后面了,实际上,overflow:hidden 声明的真正用途是防止包含元素被超大内容撑大。应用overflow:hidden 之后,包含元素依然保持其设定的宽度,而超大的子内容则会被容器剪切掉。除此之外,overflow:hidden 还有另一个作用,即它能可靠地迫使父元素包含其浮动的子元素。至于这种用法为什么会起到这种作用,是因为该设置触发了元素的Block formatting contexts(块级格式化上下文),简称 BFC,这个机制比较复杂,感兴趣的朋友可以找资料研究研究。
- 方法二:同时浮动父元素
第二种促使父元素包围其浮动子元素的方法,是也让父元素浮动起来。
#wrapper{margin:10px;border:3px solid;float: left;}
结果和上图一致,可自行校验。
- 方法三:添加非浮动的清除元素
3第三种强制父元素包含其浮动子元素的方法,就是给父元素的最后添加一个非浮动的子元素,然后清除该子元素。由于包含元素一定会包围非浮动的子元素,而且清除会让这个子元素位于(清除一侧)浮动元素的下方,因此包含元素一定会包含这个子元素——以及前面的浮动元素。在包含元素最后添加子元素作为清除元素的方式有两种。
(1)第一种方式不太理想,也就是简单地在 HTML 标记中添加一个子元素,并给它应用clear 属性。由于没有默认的样式,不会引入多余空间,div 元素很适合这个目的。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>清除浮动</title>
<style type="text/css">
*{margin: 0;padding: 0;}
#wrapper{margin:10px;border:3px solid;}
p{border:1px solid red;}
img{float: left;}
.clear_me{clear: left;}
</style>
</head>
<body>
<div id="wrapper">
<p>工欲善其事必先利其器,首先你会要用豆瓣,那里可以找到很多装逼者,共同学习,共同进步,豆瓣是个好东西,装逼必备啊。</p>
<img src="test1.jpg" />
<p>世界上总是有那么群爱装b的人,所以才有这篇不完全装b手册,为什么不完全呢?因为装的艺术是要表现在你生活的方方面面的.</p>
<div class="clear_me"></div>
</div>
<p>唐代非著名诗人章碣曾很感慨地说“刘项原来不读书”,如果能做到刘邦、项羽这么牛b的人,是不需要靠读书来装的,但一个社会同时只能容纳一个这种牛人,不可能实现大家共同装b的愿望,不利于和谐社会的建立,所以这里不推荐。</p>
</body>
</html>
(2)给父包裹元素添加:after 伪元素
这里不妨给父包裹元素添加一个clearfix的class属性
.clearfix:after {content:"."; display:block; height:0; visibility:hidden; clear:both; }
.clearfix { *zoom:1; }
它只添加了一个清除的包含句点作为非浮动元素(必须得有内容,而句点是最小的内容)。规则中的其他声明是为了确保这个伪元素没有高度,而且在页面上不可见。由于IE6-7不支持:after,使用 zoom:1触发 hasLayout。这个方法是目前最被推荐的一种方法了。需要注意的是after 会在元素内容后面而不是元素后面插入一个伪元素。
这里在延伸一下,如果这里没有父包裹元素
这三种方法的使用要因地制宜。比如,不能在下拉菜单的顶级元素上应用overflow:hidden,否则作为其子元素的下拉菜单就不会显示了。因为下拉菜单会显示在其父元素区域的外部,而这恰恰是 overflow:hidden 所要阻止的。再比如,不能对已经靠自动外边距居中的元素使用“浮动父元素”技术,否则它就不会再居中,而是根据浮动值浮动到左边或右边了。总之,掌握了这三种技术之后,再碰到需要包围浮动元素的情况,你就能够游刃有余了。
没有父元素时如何清除
有时候,在清除某些浮动元素时,不一定正好有那么个父元素可以作为容器来强行包围它们。此时,最简单的办法就是给一个浮动元素应用 clear:both,强迫它定位在前一个浮动元素下方。然而,在空间足以容纳多个元素向上浮动时,这个简单的办法未必奏效,我们还得另辟蹊径。为了演示这种情况,我们在最后一个段落前面再增加一个img。这个页面布局是通过浮动图片实现的,因此在标记中跟在图片后面的文本会向上走,停靠在浮动图片的右侧。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>清除浮动</title>
<style type="text/css">
*{margin: 0;padding: 0;}
#wrapper{margin:10px;border:3px solid;}
p{border:1px solid red;}
img{float: left;}
</style>
</head>
<body>
<p>工欲善其事必先利其器,首先你会要用豆瓣,那里可以找到很多装逼者,共同学习,共同进步,豆瓣是个好东西,装逼必备啊。</p>
<img src="test1.jpg" />
<p>世界上总是有那么群爱装b的人,所以才有这篇不完全装b手册,为什么不完全呢?因为装的艺术是要表现在你生活的方方面面的.</p>
<img src="test1.jpg">
<p>唐代非著名诗人章碣曾很感慨地说“刘项原来不读书”,如果能做到刘邦、项羽这么牛b的人,是不需要靠读书来装的,但一个社会同时只能容纳一个这种牛人,不可能实现大家共同装b的愿望,不利于和谐社会的建立,所以这里不推荐。</p>
</body>
</html>
由于第二段文字下方有空间,所以第二张图片及说明文字会上浮到第二张图片右侧,这不是我们想要的结果。我们的目标是让每段文字停靠在相应的图片旁边。然而,第二段文字太短了,都没有够到第二张浮动图片的下沿。这就给下一对儿图片/段落向上浮动留出了空间。由于每一对儿图片/段落都没有包含元素,在此就无法使用前面讨论的“强制父元素包围”的战术。不过,照样可以使用 clearfix 规则!只不过这次是将clearfix类加在段落上
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>清除浮动</title>
<style type="text/css">
*{margin: 0;padding: 0;}
#wrapper{margin:10px;border:3px solid;}
p{border:1px solid red;}
img{float: left;}
.clearfix:after{
content: ".";
display: block;
height: 0;
visibility: hidden;
clear: both;
}
</style>
</head>
<body>
<p>工欲善其事必先利其器,首先你会要用豆瓣,那里可以找到很多装逼者,共同学习,共同进步,豆瓣是个好东西,装逼必备啊。</p>
<img src="test1.jpg" />
<p class="clearfix">世界上总是有那么群爱装b的人,所以才有这篇不完全装b手册,为什么不完全呢?因为装的艺术是要表现在你生活的方方面面的.</p>
<img src="test1.jpg">
<p class="clearfix">唐代非著名诗人章碣曾很感慨地说“刘项原来不读书”,如果能做到刘邦、项羽这么牛b的人,是不需要靠读书来装的,但一个社会同时只能容纳一个这种牛人,不可能实现大家共同装b的愿望,不利于和谐社会的建立,所以这里不推荐。</p>
</body>
</html>
在每个段落内容的最后添加了“清除子元素”,我们想要的布局效果实现了。因为第三对儿图片和段落前面增加了一个清除元素,所以它们就不能再往上走了。注意,我没有只给第二个段落添加 clearfix 类,而是每个段落都加上了一个。如果是真正的网站开发,就得这么做啊。这样,无论将来哪个段落的文本高度低于图片了,页面布局都不会被破坏。
清除浮动问题,还有一些其他的方法,但是最常用的就是这三种,如果读者想掌握更多的方法,可以参考文献。
参考:
《CSS设计指南-第三版》