1. BFC
BFC(Block Formatting Context)直译为“块级格式化范围”。
是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。
当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。
比如浮动元素会形成BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。这里有点类似一个BFC就是一个独立的行政单位的意思。
也可以说BFC就是一个作用范围。可以把它理解成是一个独立的容器,并且这个容器的里box的布局,与这个容器外的毫不相干
- BFC中,盒子从包含块的顶部一个个在垂直方向上排列。
- 两个兄弟元素的垂直距离由margin决定。同一个BFC中的块级兄弟元素的垂直外边距会被叠加。
- 在BFC中,每个盒子的左外边距接触包含块的左边(从右到左的也一样),即使存在浮动元素也一样(即使盒子的行内盒子会由于浮动和紧缩,即这个盒子会由于浮动而变窄)。
解决方法:
1. 用overflow解决外边距叠加
示例:
<div class="container">
<p>Sibling 1</p>
<p>Sibling 2</p>
<p>Sibling 3</p>
<div>
<style>
.container {
width: 500px;
border: 1px solid green;
overflow: hidden;
}
p { margin: 10px 0;
background-color: lightgreen;
}
.newBFC {
overflow: hidden;
}
<style/>
效果:
从示例中我们可以看出,盒子都是从包含块的顶部开始一个接着一个垂直堆放的。
- box1 和 box2 垂直堆放, 他们里边的子元素也相互垂直堆放
子盒子1和子盒子2垂直外边距应该是20px+20px,但是并未相加,这就是垂直外边距合并
- box1浮动后不占位置, box2就跑到box1下面看不见了,但是给 box2的最后一个子元素设置 overflow: hidden 就可以显现出来
这是因为 overflow: hidden 触发了元素的 BFC ,
BFC 的特性:元素自成一个独立的盒子,从顶部按垂直方向堆放 ,垂直方向的外边距被合并了
因此就变成上图的样式了
使用 BFC 防止垂直外边距折叠
看到这里你可能有些困惑,因为在前面我们讨论了正是由于 BFC 导致外边距折叠的问题。
但是 BFC 垂直外边距折叠的问题只有当元素在同一个 BFC 时才会发生
如果不属于同一个 BFC,他们之间的外边距将不会折叠。所以通过创建一个新的BFC我们可以防止外边距折叠。
<div class="container">
<p>Sibling 1</p>
<p>Sibling 2</p>
<div class="newBFC">
<p>Sibling 3</p>
</div>
</div>
.container {
width: 500px;
border: 1px solid green;
overflow: hidden;
}
p { margin: 10px 0;
background-color: lightgreen;
}
.newBFC {
overflow: hidden;
}
效果:
让需要外边距可以正常显示的元素和其他元素分属于不同的 BFC 就可以解决外边距折叠这个问题
使用BFC来包含浮动
一个BFC可以包含浮动。很多时候我们会碰到这种情况,一个容器里有浮动元素。由于这个原因,容器元素没有高度,它的浮动孩子将会脱离页面的常规流。我们通常使用清除浮动来解决这个问题,最受欢迎的方法是使用一个 clearfix 的伪类元素。但我们同样可以通过定义一个 BFC 来达到这个目的。
示例:
<div class="container">
<div>Sibling</div>
<div>Sibling</div>
</div>
.container {
background-color: green;
overflow: hidden;
}
.container div {
float: left;
background-color: lightgreen;
margin: 10px;
}
在上面的这个案例中,如果不给父容器添加overflow: hidden,父容器将不会有任何的高度,它将不会包含已经浮动的子元素。
为了解决这个问题,我们通过添加 overflow: hidden,在容器中创建一个新的 BFC。
现在,这个容器将包含浮动的子元素,它的高度将扩展到可以包含它的子元素,在这个BFC,这些元素将会回到页面的常规文档流。
3. 使用BFC来防止文字环绕
有时候一个浮动div周围的文字环绕着它(如下图中的左图所示)但是在某些案例中这并不是可取的,我们想要的是外观跟下图中的右图一样的。
为了解决这个问题,我们可能使用外边距,但是我们也可以使用一个BFC来解决。
首先让我们理解文字为什么会环绕。为此我们需要知道当一个元素浮动时盒子模型是如何工作的。这就是我之前在讨论BFC对齐时留下的那部分。让我们从下图来了解发生了什么。著作权归作者所有。
图中的HTML可以假定为这样:
<div class="container">
<div class="floated">Floated div</div>
<p>Quae hic ut ab perferendis sit quod architecto,dolor
debitis quam rem provident aspernatur tempora expedita.
</p>
</div>
在上图中的整个黑色区域为p元素。正如我们所看到的,这个p元素并没有移动,但是它却出现在浮动元素的下方。p元素的line boxes(指的是文本行)进行了移位。此处line boxes的水平收缩为浮动元素提供了空间。
随着文字的增加,因为line boxes不再需要移位,最终将会环绕在浮动元素的下方,因此出现了那样的情况。这就解释了为什么即使在浮动元素存在时,段落也将紧贴在包含块的左边框上,还有为什么line boxes会缩小以容纳浮动元素。
如果我们能够移动整个p元素,那么这个环绕的问题就可以解决了。著作权归作者所有。
在去解决之前,让我们再回忆一下W3C标准上是怎么描述的:
在BFC中,每个盒子的左外边框紧挨着左边框的包含块(从右到左的格式化时,则为右边框紧挨)。即使在浮动里也是这样的(尽管一个盒子的边框会因为浮动而萎缩),除非这个盒子的内部创建了一个新的BFC(这种情况下,由于浮动,盒子本身将会变得更窄)
根据这些,如果这个p元素创建了一个新的BFC,那么它将不会紧挨着容器块的左边缘。这个可以通过简单的给p元素添加overflow: hidden来实现。这个方法创建了一个新的BFC解决了文字环绕在浮动元素周围的问题。
4. 在多列布局中使用BFC
如果我们正在创建的一个多列布局占满了整个容器的宽度,在某些浏览器中最后一列有时候将会被挤到下一行。会发生这样可能是因为浏览器舍入(取整)了列的宽度使得总和的宽度超过了容器的宽度。
然而,如果我们在一个列的布局中建立了一个新的BFC,它将会在前一列填充完之后的后面占据所剩余的空间。
<div class="container">
<div class="column">column 1</div>
<div class="column">column 2</div>
<div class="column">column 3</div>
</div>
.column {
width: 31.33%;
background-color: green;
float: left; margin: 0 1%;
}
.column:last-child {
float: none;
overflow: hidden;
}
现在即使容器的宽度会有轻微的变化,但是布局也不会中断。当然,这并不是多列布局的最好选择,但它是防止最后一列下滑问题的一种方法。Flexbox在这种情况下可能是一个更好的解决方案,但是这应该要说明一下在这些情况下元素是如何表现的。
触发BFC的条件:
float的属性不是none;
overflow的属性不是visible;
position的属性是absolute,fixed;
display的属性是:inline-block,table-cells,table-caption.
BFC的布局特性:
内部盒子在垂直方向一个接一个放置。
兄弟元素的外边距由margin决定,在同一个BFC里的垂直边距会叠加。(解决办法:创建一个新的BFC)
BFC的高度包含浮动元素。(可用以消除浮动)
BFC的区域不会与浮动盒子重叠。(解决图片环绕效果)
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。