浮动与清浮动(二):清浮动

ChasonZhang

上一篇文章主要总结了浮动的两种方法:display:inline-blockfloat: left/right
第一种方法的主要局限是 IE7 不支持,且换行被解析成一个空格;而第二种方法更加可取。但是要记住一点:发明 float 的初衷是为了解决图文混排的问题,因此不可滥用(就像当年滥用 table 布局一样)。

所谓“道高一尺,魔高一丈”,既然有浮动,那就必然有清浮动一说,矛盾是无处不在的。

为何要有清浮动一说?按照我最简单的理解:浮动意味着脱离了文档流(层级提升“半层”),不再按照原来的逻辑自上而自、从左到右排列元素,那么必然会对原来的元素布局产生影响,那么清浮动就是为了清除浮动带来的负面效果。比如下面一段代码:

	.div1 {
		float: left;
		width: 200px;
		height: 200px;
		background-color: red;
	}
	.div2 {
		width: 300px;
		height: 300px;
		background-color: blue;
	}
	<div class="div1">div1</div>
	<div class="div2">div2</div>

结果就会导致 div1 遮挡住一部分 div2,当然可以通过其他方法来解决这个问题,如设置 div2 的 position,但这是逃避问题,而不是解决问题(清浮动)。以下是我总结的清浮动常用方法:

clear

clear为清浮动而生,清浮动并不是并浮动的元素清除掉,而是指不允许指定元素的某个方向上出现浮动元素。clear 的常用值有:left/right/both/none,通常用 both
给上文代码中 div2 的样式添加这一属性:

	.div2 {
		clear: both;
	}

结果发现 div2 在下一行显示,且换行未被解析成空格。在 Chrome44/FF39/IE-11 下面均测试通过,棒呆!看来 clear似乎是清浮动的万能钥匙。(clear 是 CSS1 规定的属性)

“塌陷”的本质

再来测试嵌套元素中的浮动效果:

	<style type="text/css">
	body {
		margin: 0;
		padding: 0;
	}
	.div1 {
		border: 10px solid #000;
		margin: 20px auto;
		width: 600px;
	}
	.div2 {
		background-color: red;
		width: 400px;
		height: 300px;
		float: left;

	}
	</style>
	<div class="div1">
		<div class="div2"></div>
	</div>

结果在 FF39 中得到了如下的显示效果:
图片描述
去掉 div2 的 float:left,显示如下:
图片描述
可以看出,float属性使 div2 的父级元素 div1 高度变为0,俗称“塌陷”。很多人从float对父级元素的影响来解释“塌陷”,按照我个人的理解,如下:
我们回归 float 的本质,浮动会导致当前元素脱离文档流,提升自身层级“半层”,也就是说浮动的元素也就不再属于原来的层级,在这里来说,从显示效果(样式)上看: div2 也就不再是 div1 的子元素。
在这个例子中,再添加 div3:

	<div class="div3"></div>
	.div3 {
		width: 600px;
		border: 10px solid #000;
		margin: 0 auto;
	}

在 FF39 中得到如下效果:
图片描述
也就是说,div 块级元素的内容为空时,其 Content Width/Height = 0。既然浮动元素不再属于原来的父级元素,那父级元素里里就是空的,因此也就无所谓“塌不塌陷”一说了。借用一句禅语:“本来无一物,何处惹尘埃!”

总结上文,在结构(HTML)上,div2 属于 div1。但是,在形式(CSS)上,div2 不属于 div1。也就是说,这是结构和形式分离带来的矛盾。而清浮动,在某种意义上就是为了清除这一矛盾。

清浮动:父级元素

清浮动,无非从两方面着眼,一是父级元素本身,二是父级元素里的内容。
一、从父级元素本身来:
既然是由于父级元素和子级元素不在同一层级,那么可以给父级元素添加浮动:float/display:inline-block
图片描述
但是,这种方法的缺陷在于:改变了父级元素的样式,还要添加其他样式,增加了工作量,如果是多层嵌套的话,那势必要修改多个父级元素的样式,“子子孙孙无穷尽也”~

清浮动:子级元素

二、从子级元素考虑,也就是从父级元素里的内容考虑:
既然是因为父级元素 div1 中没有内容导致的,那可以考虑在 div1 里面加点料:

方法1:

	.clear{
		clear: both;
        height: 0;    // 解决 IE6 下最小高度19px的问题
		font-size: 0;    // 解决 IE6 下最小高度19px的问题
	}
	<div class="clear"></div>

经测试,IE7(包括)以上,加注释的两行不写其实也没关系。

方法2:

	<br clear='both'>

IE6 以上全兼容,关于<br clear='both'>这一行,可以查阅 w3c 中文网的解释

方法3:

方法1和方法2的缺陷在于,需要在<HTML>中添加内容。为了改变样式而添加内容,这违背了结构与样式分享的原则。
因此,可以考虑采用伪类:after,并结合方法2:

	.clear {
		zoom: 1;    // zoom 是 IE6 私有属性
	}
	.div1:after {
		content: '';
		display: block;
		clear: both;
	}
	<div class="div1 clear">
		<div class="div2"></div>
	</div>

带注释的一行是专门针对 IE6 的小 hack,因为刚装了 Win10,IETester 好像出了点问题不能用了,因此没测试 IE6 下的兼容性,IE7 及以上均测试通过。
关于 zoom,可以阅读这一篇文章:CSS中不为人知Zoom属性的使用介绍(IE私有属性)

关于浮动与清浮动,目前个人的总结基本就是这两篇了。

阅读 2.8k

产品经理学技术
记录我的代码学习之路。

杂食喵科产品汪

767 声望
23 粉丝
0 条评论
你知道吗?

杂食喵科产品汪

767 声望
23 粉丝
宣传栏