CSS:BFC 最熟悉的陌生人

BFC,你也许听过这个词,但是你可能不是很有底气地解释清楚。
写样式的时候,往往加了一个样式或者改了一个属性,就能达到你期望的效果,一切都是如此地神奇。
BFC就是神奇之一,它也是最熟悉的陌生人,因为你一不小心就会触发它然而你并没有意识到它正在神奇地发挥作用。

一、初探BFC

我们先看看CSS布局的基本单位:

  • block-level box: display 属性为 block, list-item, table 的元素,会生成 block-level box,并且参与 block formatting context
  • inline-level box: display 属性为 inline, inline-block, inline-table 的元素,会生成 inline-level box,并且参与 inline formatting context

那这个formatting context又是什么玩意儿?

它是W3C CSS2.1规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。也就是说我们平时在布局的时候,它默默地提供了一个环境,使得HTML元素在这个环境中按照一定规则进行布局。

最常见的formatting context有Block Formatting Context(BFC)和Inline Formatting Context(IFC),CSS3中还增加了GridLayout Formatting Context(GFC)和Flex Formatting Context(FFC),这里就不深入研究了。

BFC定义:它是一个独立的渲染区域,只有block-level box参与,其中的元素按照规定的渲染规则进行布局,并且这个区域与外部毫不相干。

二、BFC的布局规则与触发规则

刚才我们说到BFC中的元素有一套规定的布局规则

  • 内部的元素会在垂直方向一个接一个地放置
  • 元素垂直方向的距离由margin决定,属于同一个BFC的两个相邻元素的margin会发生重叠
  • 每个元素的左外边距与包含块的左边界相接触(对于从左往右,否则相反),即使存在浮动也是如此
  • BFC的区域不会与float元素重叠
  • 计算BFC的高度时,浮动元素也参与计算
  • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之也如此

刚才我们又提到BFC是一块渲染区域,那这块渲染区域到底在哪,它又是有多大,这些由生成BFC的元素来决定,CSS2.1中规定满足下列CSS声明的元素便会生成BFC(触发规则):

  • 根元素
  • float的值不为none
  • overflow的值不为visible
  • position的值为absolute或fixed
  • display的值为inline-block, table-cell, table-caption, flex, inline-flex
    注:display: table也认为可以生成BFC,主要原因是table会默认生成一个匿名的table-cell,正是这个匿名的table-cell生成了BFC

上面这些CSS声明的元素生成了BFC,而它们本身并不是BFC,这一点需要区分。

三、BFC的应用

说了这么多有用没用的,我们平时布局的时候到底怎么应用呢:

1.防止垂直margin重叠

有点布局经验的朋友都知道margin collapse,也就是相邻的垂直元素同时设置了margin后,实际margin值会塌陷到其中较大的那个值。其根本原理就是它们处于同一个BFC,符合“属于同一个BFC的两个相邻元素的margin会发生重叠”的规则。

我们可以在其中一个元素外面包裹一层容器,并触发该容器生成一个BFC。那么两个元素便属于不同的BFC,就不会发生margin重叠了:

<style>
    .wrap{
        overflow: hidden;
    }
    p{
        width: 200px;
        line-height: 100px;
        margin: 100px;
        background: #000;
        color: #fff;
        text-align: center;
    }
</style>

<body>
    <p>我属于一个BFC</p>
    <div class="wrap">
        <p>我属于另一个BFC</p>
    </div>
</body>

图片描述

如果是我的话会直接设置200px,或者只设置其中一个元素的margin(懒可以偷,但原理需知道)

2.防止浮动子元素高度塌陷

<style>
    .parent{
        width: 300px;
        border: 3px solid #000;
        overflow: hidden;
    }
    .child{
        float: left;
        width: 100px;
        height: 100px;
        border: 3px solid #f00;
        color: #f00;
    }
</style>

<body>
    <div class="parent">
        <div class="child">float: left</div>
        <div class="child">float: left</div>
    </div>
</body>

图片描述

如果我们将.parent元素的overflow: hidden去掉,那么.parent元素就获取不到浮动元素的高度了。但是加上overflow属性后触发了BFC,计算BFC的高度时,浮动元素也参与了计算。

3.防止文字(或其他元素)环绕

<style>
    .parent{
        width: 300px;
        border: 3px solid #000;
    }
    .child{
        float: left;
        width: 100px;
        height: 100px;
        border: 3px solid #f00;
        color: #f00;
    }
    .text{
        overflow: hidden;
    }
</style>

<body>
    <div class="parent">
        <div class="child">float: left</div>
        <div class="text">我只是文字但我不会环绕我只是文字但我不会环绕我只是文字但我不会环绕我只是文字但我不会环绕我只是文字但我不会环绕我只是文字但我不会环绕我只是文字但我不会环绕我只是文字但我不会环绕我只是文字但我不会环绕我只是文字但我不会环绕</div>
    </div>
</body>

图片描述

正常情况下,如果一个块级元素设置成了float,那么他的兄弟元素会环绕其布局。这里我们给.text加上overflow,文字所在的区域就产生了BFC,元素的左边总是触碰到容器的左边,即使存在浮动也是如此。

这里举例了几个比较经典的应用,我们在以后的布局中也可以慢慢探索其中的奥秘之处,做一个能写一手好样式还能懂原理的前端er。

1 篇内容引用

致力于前端开发、

94 声望
3 粉丝
0 条评论
推荐阅读
HTTP2前世今生
在我们所处的互联网世界中,HTTP协议算得上是使用最广泛的网络协议了。HTTP建立之初,主要就是为了将HTML从web服务器传送到客户端的浏览器。但是近几年web发展非常迅速,我们的页面变得复杂起来,有很多动画效果...

Mr_Nice3阅读 1.5k

还在用 JS 做节流吗?CSS 也可以防止按钮重复点击
举个例子:一个保存按钮,为了避免重复提交或者服务器考虑,往往需要对点击行为做一定的限制,比如只允许每300ms提交一次,这时候我想大部分同学都会到网上直接拷贝一段throttle函数,或者直接引用lodash工具库

XboxYan34阅读 2.3k评论 2

封面图
CSS 如何设置自动滚动定位的“安全”间距?
欢迎关注我的公众号:前端侦探介绍两个和滚动定位相关的 CSS 属性:scroll-padding和 scroll-margin在平时开发中,经常会碰到需要快速定位的问题,比如常见的锚点定位 {代码...} 这样,在点击a标签时会自动定位到...

XboxYan30阅读 2.2k评论 2

封面图
CSS transition 小技巧!如何保留 hover 的状态?
欢迎关注我的公众号:前端侦探通常情况下,hover 是无法保存状态的。鼠标移入触发额外样式,一旦移出就还原了 {代码...} 这就意味着,如果需要保留hover的状态,可能就不得不借助JS了,比如下面是某某书院的首页...

XboxYan29阅读 3.5k评论 2

封面图
现代 CSS 之高阶图片渐隐消失术
在过往,我们想要实现一个图片的渐隐消失。最常见的莫过于整体透明度的变化,像是这样: {代码...} {代码...} 但是,CSS 的功能如此强大的今天。我们可以利用 CSS 实现的渐隐效果已经不再是如此的简单。想想看,...

chokcoco25阅读 2.1k

封面图
除了 filter 还有什么置灰网站的方式?
大家都知道,当一些重大事件发生的时候,我们的网站,可能需要置灰,像是这样:当然,通常而言,全站置灰是非常简单的事情,大部分前端同学都知道,仅仅需要使用一行 CSS,就能实现全站置灰的方式。像是这样,我...

chokcoco19阅读 1.6k评论 1

封面图
万能的CSS 渐变!单标签绘制一个足球场
一眼望去,这里的形状只有圆形和矩形,在不借助其他标签的情况下(包括伪元素),其实很容易联想到渐变,一起看看如何绘制的吧,有非常多的渐变小技巧~

XboxYan18阅读 1.9k评论 8

封面图

致力于前端开发、

94 声望
3 粉丝
宣传栏