清除浮动有哪几种方法?
父元素算高度时不包含浮动子元素,导致高度塌陷。解决办法有三类:在浮动后面放一个 clear 元素,常用 ::after 伪元素写成 clearfix;让父元素创建 BFC,首选 display: flow-root,overflow: hidden 也行但会裁剪内容;或者不用浮动,改用 Flex 和 Grid 布局。
简答
父元素里只有一张左浮动的图片,父元素的高度会变成 0,背景和边框缩成一条线,图片“掉”到了外面。这叫高度塌陷,原因是普通块元素计算高度时不把浮动的子元素算进去。“清除浮动”就是让父元素重新把浮动包住。
第一种方法是在浮动元素后面放一个设置了
clear: both的块。clear让这个元素移到前面所有浮动的下方,父元素要包住它,高度自然就撑开了。现在一般不额外写空标签,而是用::after伪元素来做,也就是常说的 clearfix。第二种方法是让父元素创建 BFC,也叫块格式化上下文,BFC 的高度会包含内部的浮动。最直接的写法是
display: flow-root。overflow: hidden也能创建 BFC,但它会把超出的阴影、下拉菜单裁掉。第三种是从根上避免:两栏、多栏布局现在用 Flex 或 Grid 写,不再依赖浮动。浮动只留给“图片在左、文字环绕”这种它本来的用途。
三种写法放在一起看
下面三个父元素里都只有一个 50px 高的左浮动块。在 Chrome 中用 headless 模式实测,三个父元素的高度都是 50px;去掉这些写法,父元素高度是 0。
.float-child {
float: left;
height: 50px;
}
/* 方法一:clearfix */
.clearfix::after {
content: '';
display: block;
clear: both;
}
/* 方法二:创建 BFC */
.flow-root {
display: flow-root;
}
/* 方法二的旧写法,会裁剪溢出内容 */
.overflow-hidden {
overflow: hidden;
}
clearfix 为什么要写 content: '' 和 display: block?::after 没有 content 就不会生成,而 clear 只对块级盒子起作用,行内的伪元素清不了浮动(用 headless Chrome 实测,把 clear: both 写在一个行内 span 上,父元素高度仍是 0)。MDN 对 clear 的说明是,它让元素移到前面的浮动元素下方,both 表示左右两侧的浮动都要清。伪元素成为父元素里最后一个块,又被推到了浮动下面,父元素为了包住它就得把高度撑到浮动底部。
为什么 BFC 能包住浮动
MDN 列出的 BFC 作用之一就是“包含内部的浮动”。哪些元素会创建 BFC 呢?浮动元素本身、绝对定位元素、overflow 不是 visible 或 clip 的块,以及 display: flow-root 的元素,等等。
flow-root 是专门为创建 BFC 设计的值,没有别的副作用。overflow: hidden 是借用裁剪功能顺带创建 BFC,MDN 也提醒这样做可能出现多余的滚动条或者被裁掉的阴影。所以新代码优先用 flow-root。BFC 的其他用途,比如阻止外边距折叠、让块避开旁边的浮动,见《BFC 解决哪些布局问题,什么时候用 flow-root?》。
常见追问
给父元素设固定高度算不算清除浮动?
能让外观看起来正常,但父元素不会跟着内容变高,内容多了还是会溢出,所以不算可靠的办法。
clear 只能写在父元素里吗?
不是。
clear可以用在任何块元素上,比如浮动图片后面的一段正文加clear: both,这段文字就会从图片下方开始,不再环绕图片。clearfix 只是把它用在父元素的最后一个伪元素上。