携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
浮动
浮动是网页布局中最古老的方式,并且在过去很年都是唯一的方式。
容器折叠
容器折叠就是我们常说的高度坍塌问题。该问题的来源是由于子元素设置了浮动,导致父元素不能被子元素撑开。因为浮动元素不同于普通文档流的元素,浮动元素的高度不会增到父元素上。
来看一个例子
<style>
.container{
width: 200px;
padding: 10px;
background: red;
}
.child{
width: 100px;
height: 100px;
float: left;
background-color: green;
}
</style>
<div class="container">
<div class="child"></div>
</div>
查看网页上的效果会发现, .container 盒的高度只有 20px , 也就是设置的 padding 。 这在很多时候并不是我们想要的效果,另外浮动也会导致一些其他问题,例如:
- 文字围绕浮动元素排版,但是我们并不希望浮动元素两边有元素存在,这时候我们就需要清除浮动。
- 浮动元素影响到了其他的兄弟元素的布局位置,因为浮动元素脱离的文档流,因此浮动元素后面的兄弟元素在进行位置计算时,会把浮动元素当作不存在,紧接着上一个元素进行排列。
这里插一句题外话, 文字围绕浮动元素排版,这是浮动设计的初衷,最开始用于设置报纸和杂志新闻页面
要解决这个问题,我们有两种方式
- 使用
clear清除浮动 - 触发父元素的
BFC
清除浮动的方式
使用 clear 属性清除浮动
对于上面的例子,我们可以像下面这样修改,能够解决父元素高度塌陷的问题
<style>
.container{
width: 200px;
padding: 10px;
background: red;
}
.child{
width: 100px;
height: 100px;
float: left;
background-color: green;
}
.box{
clear: left;
/** 属性值设置成 both 同样有效 */
/* clear: both; */
}
</style>
<div class="container">
<div class="child"></div>
<!-- 在浮动元素后面新增一个元素 -->
<div class="box"></div>
</div>
使用这种方式会增加不必要的空白元素,不够优雅。那么我们可以使用伪元素的方式来清除浮动
.container::after{
content: "";
display: block;
clear: both;
}
通过伪元素的方式,就可以在不添加新的元素的情况下达到清除浮动的目的。这里有两点需要注意的地方
-
::after伪元素是添加在 包含浮动元素的元素上, 也就是浮动元素的父元素
-
- 需要将
::after伪元素的display值设置成非inline的值,例如block、table, 只要不是行内元素都可以, 行内块元素也不行, 因为clear属性无法用于行内元素
- 需要将
clear 属性清除浮动的原理
从字面意思来看, clear 确实有清除的意思, 那么 clear: left; clear: right; 分别是清除左浮动和清除右浮动。 这种理解是不正确的,因为浮动一直存在,并没有被清除。
来看下 W3C 对 clear 属性的解释:
This property indicates which sides of an element's box(es) may not be adjacent to an earlier floating box. The 'clear' property does not consider floats inside the element itself or in other block formatting contexts.
Values have the following meanings when applied to non-floating block-level boxes:
left
Requires that the top border edge of the box be below the bottom outer edge of any left-floating boxes that resulted from elements earlier in the source document.
right
Requires that the top border edge of the box be below the bottom outer edge of any right-floating boxes that resulted from elements earlier in the source document.
both
Requires that the top border edge of the box be below the bottom outer edge of any right-floating and left-floating boxes that resulted from elements earlier in the source document.
none
No constraint on the box's position with respect to floats.
简单总结一句话就是: 元素盒子的边框不能与前面的浮动元素相邻, 这里说的相邻是左右相邻, 并且这里的浮动元素值得也是在需要清除浮动的元素的前面设置了浮动的元素。也就是说,指的是前面设置了浮动的兄弟元素。对后面的设置了浮动的兄弟元素是不管的。
那么 clear 属性值设置为 left 、 right 、 both 有什么区别呢?
对上面 W3C 对三个不同属性值的解释进行总结分析:
-
left:元素盒子不能与前面设置左浮动的元素相邻,可以理解成元素盒子的左边不能有浮动元素,既然左边不能有浮动元素,那么就只好排在浮动元素的下面咯 -
right:元素盒子不能与前面设置右浮动的元素相邻,可以理解成元素盒子的右边不能有浮动元素,既然右边不能有浮动元素,那么就只好排在浮动元素的下面咯 -
both:元素盒子既不能与前面设置了左浮动的元素相邻,也不能和前面设置了右浮动的元素相邻,也就是说,元素盒子的两边都不能有浮动元素
触发 BFC
触发父元素的 BFC 也是解决父元素高度塌陷的一个办法, 至于触发 BFC 的方法有很多中,这里不详细说明,在这里主要了解一下什么是 BFC , 以及 BFC 有哪些特点
BFC 是 block formatting context (块级格式化上下文)的缩写。 BFC 是网页的一块区域,元素基于这块区域布局,也是浮动元素和其他元素交互的区域。触发了 BFC 的区域有以下特点
-
BFC的元素不会与周围的浮动元素重叠<style> .child{ width: 100px; height: 100px; float: left; background-color: green; } .box{ width: 150px; height: 100px; overflow: hidden; /** 触发 BFC*/ background-color: black; } </style> <div class="container"> <div class="child"></div> <div class="box"></div> </div>上面的例子中,触发
.box元素的BFC之后, .box 元素不会和.child元素发生重叠 -
计算
BFC元素高度是,会包括浮动元素。 这也就是为什么能解决高度塌陷的问题 -
在同一个
BFC下的块会发生margin塌陷问题,不在同一个则不会 -
BFC元素是一个独立的容器,使得里面的元素和外部元素隔离开,互不影响
浮动陷阱
在开发过程中,常会遇到多行多列的布局,例如下图:

在每一行的元素盒子高度相等的情况下,元素会按照我们期望的进行排列。但是如果说,元素盒子的高度是由内容撑开的, 那么元素盒子的高度可能不想等,就可能出现超出预期的布局,像下面这样
会发现, box3 盒子并没有浮动到最左边,也就是 box1 下面,而是排列在了 box2 下面。这是为什么呢???
答案很简单,浏览器在对浮动元素进行排列时,会尽可能的将浮动元素放在靠上的地方,由此就出现了上面的情况。那么这并不是我们想要的效果。要修复这个问题其实也很简单: 我们只需要清除第二行第一个元素,也就是 box3 上面的浮动即可。通过上面对 clear 属性的原理的分析,我们知道,清除 box3 的浮动之后, box3 盒子的两侧不能出现浮动元素(假设设置 clear: both) ,那么 box3 就会排列在浮动元素的下面,这就是找到高度最高的那个元素,并排列在该元素下方。
浮动和 margin 塌陷
先来看一段代码
<style>
.container-1{
width: 100px;
height: 100px;
margin-top: 100px;
background-color: red;
}
.child-1{
width: 50px;
height: 50px;
margin-top: 50px;
background-color: green;
}
</style>
<div class="container-1">
<div class="child-1"></div>
</div>
很容易看出,上面的 .child-1 和 .container-1 父子元素之间发生了 margin 塌陷问题。解决 margin 塌陷有很多种方法,这里就不详细说明了。
如果我们给子元素,也就是 .child-1 元素添加上浮动,会发生什么呢? 会发现, 父子元素之间没有在出现 margin 塌陷的问题,这是因为浮动元素和绝对定位的元素永远不会发生 margin 塌陷。但是添加浮动并不适用于解决 margin 塌陷问题,这可能会引入新的问题。
如果这篇文章对你有一点小小的帮助,请给我一个赞,鼓励我!!!