css中的浮动影响以及清除浮动的几种方式
一直没有深入去了解过浮动造成的影响,只是知道会高度塌陷,至于为什么就不知道了。梳理css中的基础知识带给我类似读源码似的效果,知其然和所以然,对需要进阶的我来说很重要。
浮动的效果
浮动会让元素脱离文档流,让元素向左或者向右贴到父元素的边。
浮动的问题
我们想实现左右布局,于是给111和222设置了左右浮动,结果变成了下面这样,父元素高度没了:
image.png<body>
<style>
.container {
width: 200px;
border: 1px solid #000;
}
.box {
width: 50px;
height: 50px;
}
</style>
<div class="container">
<div class="box a" style="background: red;float: left;">111</div>
<span class="box b" style="background: yellow;float: right;">222</span>
</div>
</body>
这里就出现了浮动的影响:
1、div原本独占一行,设置浮动之后,脱离文档流,不再独占一行,后面的元素会挤上来。
2、span等行内标签,设置浮动之后可以直接设置宽高。
3、浮动之后元素的层级会高于普通元素,低于定位元素。
4、浮动会脱离文档流,所以这个元素不再会撑开父元素,造成父元素高度塌陷,不再是我们设想的效果。
5、我们给浮动元素后面再加一个元素:
<body>
<style>
.container {
width: 200px;
border: 1px solid #000;
}
.box {
width: 50px;
height: 50px;
}
</style>
<div class="container">
<div class="box a" style="background: red;float: left;">111</div>
<span class="box b" style="background: yellow;float: right;">222</span>
<div class="box c" style="background: blue;">333</div>
</div>
</body>
浏览器审查元素可以看到,由于111和222已经脱离了文档流,父元素的高度实际是由333撑开的,333和111的位置实际是重叠了,需要修改333的层级才能正确显示,如下图:
image.png不过文字333已经不在自己的内容区域之内了,这里为什么呢?
我在网上没有找到比较明确的答案,暂时这么理解,如果有知道此原理的同学请指正。
浮动的功能最初被设计出来只有img才支持此属性,因为当时想实现文字环绕图片的效果,后来所有元素都支持了浮动。如上图,333虽然位置和111重叠了,但是333的文字依然会去环绕111。
如何清除浮动
1、给父元素设置高度
如果一个元素要浮动,那么它的父元素可以通过设置高度来解决,实际应用中我们不大可能给所有的盒子加高度,不仅麻烦,并且不能适应页面的快速变化。
注意:这里虽然包裹住了333的文字,但审查元素依然是111和333的位置是重叠的
image.png<body>
<style>
.container {
width: 200px;
border: 1px solid #000;
/* 通过高度撑开,解决高度塌陷问题 */
height: 200px;
}
.box {
width: 50px;
height: 50px;
}
</style>
<div class="container">
<div class="box a" style="background: red;float: left;">111</div>
<span class="box b" style="background: yellow;float: right;">222</span>
<div class="box c" style="background: blue;">333</div>
</div>
</body>
2、给父元素添加overflow属性
这种方案让父容器形成了BFC(块级格式上下文),而BFC可以包含浮动,通常用来解决浮动父元素高度坍塌的问题。
这里可以给父元素设置overflow:auto,但是为了兼容IE最好使用overflow:hidden。
但这种办法有个缺陷:如果有内容出了盒子,用这种方法就会把多的部分裁切掉,所以这时候不能使用。
注意:111此时和333是重叠的。
image.png<body>
<style>
.container {
width: 200px;
border: 1px solid #000;
overflow: hidden;
}
.box {
width: 50px;
height: 50px;
}
</style>
<div class="container">
<div class="box a" style="background: red;float: left;">111</div>
<span class="box b" style="background: yellow;float: right;">222</span>
<div class="box c" style="background: blue;">333</div>
</div>
</body>
BFC的触发方式我们可以给父元素添加以下属性来触发BFC:
- float 为 left | rightoverflow 为 hidden | auto | scorll
- display 为 table-cell | table-caption | inline-block
- position 为 absolute | fixed
BFC的主要特征:
BFC容器是一个隔离的容器,和其他元素互不干扰;所以我们可以用触发两个元素的BFC来解决垂直边距折叠问题。
BFC不会重叠浮动元素
BFC可以包含浮动,这可以清除浮动。
3、使用带clear属性的空元素
在浮动元素后面新添加一个冗余元素,然后将其设置clear:both,这样就可以清除浮动。这里强调一点,即在浮动元素后面添加的元素必须是一个块级元素,否则无法撑起父级元素高度。
优点:简单,代码少,浏览器兼容性好。
缺点:需要添加大量无语义的html元素,代码不够优雅,后期不容易维护。
注意:在不同的位置添加的块级元素会让333换行,呈现结果也不一致
image.png<body>
<style>
.container {
width: 200px;
border: 1px solid #000;
}
.box {
width: 50px;
height: 50px;
}
</style>
<div class="container">
<div class="box a" style="background: red;float: left;">111</div>
<!-- 这里添加空的div具有换行效果,可以让333的文字处在自己的区域内 -->
<!-- <div style="clear: both;"></div> -->
<span class="box b" style="background: yellow;float: right;">222</span>
<!-- 这里添加空的div具有换行效果,可以让333的文字处在自己的区域内 -->
<!-- <div style="clear: both;"></div> -->
<div class="box c" style="background: blue;">333</div>
<div style="clear: both;"></div>
</div>
</body>
4、br标签清浮动
这种方式类似于在浮动元素后添加<div style="clear: both;"></div>
。只是换了一个标签和属性:
<br />
标签有一个clear
属性,为其设置all
值就可以了。缺点还是不够优雅,需要添加大量无语义的html元素,代码不够优雅,后期不容易维护。
<body>
<style>
.container {
width: 200px;
border: 1px solid #000;
}
.box {
width: 50px;
height: 50px;
}
</style>
<div class="container">
<div class="box a" style="background: red;float: left;">111</div>
<span class="box b" style="background: yellow;float: right;">222</span>
<br clear="all" />
<div class="box c" style="background: blue;">333</div>
</div>
</body>
5、伪元素清除浮动
类似于在元素后面添加一个空标签,不过是使用伪元素来替代空标签,可以直接用一个通用的类名来解决,而不用去添加空标签,因此这也是使用最广泛最优雅的解决办法。
image.png
<body>
<style>
.container {
width: 200px;
border: 1px solid #000;
}
.box {
width: 50px;
height: 50px;
}
.clearfix::after {
content: '';
/* 需要设置为块元素,原因跟上面几个方法一样 */
display: block;
clear: both;
}
</style>
<div class="container clearfix">
<div class="box a" style="background: red;float: left;">111</div>
<span class="box b" style="background: yellow;float: right;">222</span>
<div class="box c" style="background: blue;">333</div>
</div>
</body>
上面如有不正确的地方请指正,谢谢。