清除浮动与BFC

1,328 阅读6分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

浮动

指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。该元素从网页的正常流动(文档流)中移除

简单来说,float属性会可能远地向左或向右浮动一个元素,然后它下面的元素会绕流这个元素(绕着这个元素流动)。

<section>
    <div class="right">
      <span>float:right</span>
      <span>float:right</span>
      <span>float:right</span>
    </div>
    <div class="normal"><span>我需要环绕右边</span></div>
    <div class="normal"><span>我需要环绕右边</span></div>
</section>
section {
  border: 1px solid blue;
}

.right {
  float: right;
  background-color: bisque;
}

.normal {
  background-color: aqua;
}

脱离文档流

当元素设置floatleftright时,元素会脱离文档流。脱离文档流主要有以下几个表现:

  1. 不再受标准流的约束
  2. 不能将父元素撑开
  3. 块级元素和行内元素设置float的区别
  • 块级元素标准流下会独占一行,而脱离后宽度将由内容撑开
  • 行内元素标准流下由内容撑开,设置宽高无效,但脱离后可以设置宽高,且垂直方向上的margin也会起效

举例来看:

.right {
  float: right;
  background-color: bisque;
  height: 50px;
  margin-top: 10px
}
<section>
  <span class="right">float:right</span>
  <span class="right">float:right</span>
  <div class="normal"><span>我需要环绕右边</span></div>
  <div class="normal"><span>我需要环绕右边</span></div>
</section>

这是为什么呢?

当不同元素进行了脱标,对应会展示成display的何种属性值?MDN有相应的解释

清除浮动

常见的清除浮动到底是什么呢?

  1. 有时候可能想要强制元素移至任何浮动元素下方。比如可能希望某个段落与浮动元素保持相邻的位置,但又希望这个段落从头开始强制独占一行
  1. 浮动溢出:当元素设置浮动后,父元素高度为auto时,会造成父元素高度不能自动伸长以适应浮动内容的高度,使得浮动内容溢出到父元素外面而影响布局的现象。
.news {
  height: auto;
  background-color: gray;
  border: solid 1px black;
}

.news img {
  float: left;
}

.news p {
  float: right;
}
<div class="news">
  <img src="img.jpg" />
  <p>some text</p>
</div>

正常的布局应该是下面这样,下面来看到底如何解决它吧

明白了什么是浮动溢出,接下来我们需要去清除这种布局混乱的现象,达到布局既不混乱,浮动仍有效的目的。一般有两种方式:

  • clear属性
  • 触发BFC

下面来介绍这两种方式。

clear属性

它指定一个元素是否必须移动到在它之前的浮动元素下面

常用属性:

  • none 元素不会向下移动清除之前的浮动。

  • left 元素被向下移动用于清除之前的左浮动。

  • right 元素被向下移动用于清除之前的右浮动。

  • both 元素被向下移动用于清除之前的左右浮动。

举个简单的例子

.wrapper {
  border: 1px solid black;
  padding: 10px;
}

.left {
  border: 1px solid black;
  margin-top:20px;
  clear: right;
}

.black {
  float: left;
  margin: 0;
  background-color: black;
  color: #fff;
  width: 20%;
}

.red {
  float: right;
  margin: 0;
  background-color: pink;
  width: 20%;
}
<div class="wrapper">
  <p class="black">this is black</p>
  <p class="red">this is red this is red this is red this is red this is red this is red</p>
  <p class="left">This paragraph clears right.</p>
 </div>

classleft的元素确实清除了右侧红框的浮动,但是它的垂直外边距被折叠了。

当clear属性应用于非浮动块时,所以它将非浮动块的边框边界移动到所有相关浮动元素外边界的下方。这个非浮动块的垂直外边距会折叠。

而当应用于浮动元素时,它将元素的外边界移动到所有相关的浮动元素外边界的下方,所以不会造成折叠。但是这会影响后面浮动元素的布局,后面的浮动元素的位置无法高于它之前的元素。

注意点

它是应用在块级元素上的属性。为什么没有应用在内联元素呢?因为float的设计初衷就是为了实现文字环绕图片,本身就是做图文混排的。注意:早期的css标准有,后来只用在块级元素上起效。

BFC

定义

块格式化上下文(Block Formatting Context)。MDN上给出的定义是:

Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。

这个定义解释十分抽象,需要实际应用来理解。主要通过设置BFC和不设置BFC的区别来理解它的作用。

常见创建bfc的方式

  • 根元素html
  • 浮动元素 float不是none
  • 绝对定位元素 positionabsolutefixed
  • 行内块元素displayinline-block
  • overflow不为visible的块元素
  • 弹性元素
  • 网格元素

BFC的作用

清除浮动

上文提到BFC可以清除浮动,依旧是上面redmi的例子

.news {
  background-color: gray;
  border: solid 1px black;
  height: auto;
  overflow: hidden;
}

设置了overflow:hidden属性,将news变成了BFC,在计算高度的时候,内部浮动元素的高度也要计算在内,这正解释了定义说这是浮动元素与其他元素交互的位置,因为未设置BFC时,news内部对的浮动元素和父元素看似并无关系,它已经脱离了文档流,但是当父元素设置BFC后,将浮动元素的高度也计算在内了,BFC的高度也不会发生塌缩。

解决垂直外边距重叠

.blue,
.red{
  width: 50px;
  height: 50px;
  margin: 10px 0;
}

.blue {
  background: blue;
}
.red{
  background: red;
}
<div class="blue">blue</div>
<div class="red>red</div>

可以看出blue和red垂直边距重叠了

改成

<div class="blue">blue</div>
<div style="overflow:auto">
  <div class="red>red</div>
</div>

BFC的区域不会和外部盒子的外边距区域发生叠加,可以说BFC像是隔离了内部和外部,内部不会受到元素渲染的影响,内部进行着自己的一套规则,也不影响外部渲染。

设置两栏布局

.box {
  background-color: rgb(224, 206, 247);
  border: 5px solid rebeccapurple;
  overflow: auto;
}

.float {
  float: left;
  width: 200px;
  height: 150px;
  background-color: white;
  border: 1px solid black;
  padding: 10px;
}
<div class="box">
  <div class="float">I am a floated box!</div>
  <div class="content">I am content inside the container.</div>
</div>

content会环绕着float进行流动

但是当给content设置overflow: hidden;后,contentfloat内容互不影响,content不再环绕着float进行流动,由此形成了两栏布局。

当构建BFC区域的元素紧接着一个浮动盒子时,即该浮动盒子的兄弟节点,BFC区域会首先尝试在浮动盒子的旁边渲染,但若宽度不够,就在浮动元素的下方渲染。

总结

  1. 当元素设置floatleftright时,元素会脱离文档流,脱离文档流后块级元素和行内元素有一些改变,本质是display的计算值被修改;
  2. 清除浮动一般有两种主要的方法,一个是使用clear属性,另一个是触发BFC;
  3. 理解BFC原理后也可解决一些其他问题,如垂直边距重叠,实现两栏布局等等;
  4. 除了设置overflow来清除浮动,其他的方式也可以,如果单纯使用属性来清除浮动的话,更常用overflow,影响更加可控。