BFC是啥?(清除浮动与外边距合并问题)

BFC是什么?

入门FE了那么久,BFC这个名词倒是第一次知道,特地前去了解了一下,幡然醒悟,这不就是平常我们写block和inline的标准文档流吗?(恕我不专业的描述方式),估计是自己知识面太窄了,不然咋会在学习CSS的时候错过捏,呵呵哒。

Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with ‘overflow’ other than ‘visible’ (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.
————W3C

中文直译为块级格式上下文(或块级上下文)。其实就是我们平常的块级元素自顶向下排列,同级之间的containing block顶部一个接一个垂直排列,水平方向上撑满宽度。
因为两个相邻的BFC之间距离由margin决定,在同一个BFC内部,两个垂直方向相邻的块级元素margin值会"共用",导致塌陷。也是经典的外边距塌陷问题。

以下方法可以创建一个新的块级执行上下文(BFC):
  • 浮动元素
  • 绝对定位元素
  • 块级元素以及块级容器(比如inline-block、table-cell、table-capation)
  • overflow值不为visible的块级盒子
    当然,root元素会自动生成一个BFC,这个应该很好理解,毕竟需要一个根BFC来布局
执行规则:
  1. 在一个块级排版上下文中,盒子是从包含块顶部开始,垂直的一个接一个的排列的。每个盒子的左外边是触碰到包含块的左边的(对于从右向左的排版,则相反)
  2. 相邻两个盒子之间的垂直的间距是被margin属性所决定的,在一个块级排版上下文中相邻的两个块级盒之间的垂直margin是折叠的。

注意:这里着重了解一下,什么是同一个BFC、根BFC,有何区别


我们来实现它。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            div {
                width: 200px;
                height: 100px;
            }
            .a {
                background-color: red;
            }
            .b {
                background-color: orange;
            }
            .c {
                background-color: deepskyblue;
            }
            .d {
                background-color: black;
                margin: 20px;
            }
            .e {
                background-color: green;
                margin: 20px;
            }
        </style>
    </head>
    <body>
        <div class="a"></div>
        <div class="b"></div>
        <div class="c"></div>
        <div class="d"></div>
        <div class="e"></div>
    </body>
</html>
示例1
实例一

这是最普通的块级排版上下文,现在问题来了,这里有新的BFC吗?对比那4个方法......没有对吗,所以,这里的所有class都是同一种BFC或者说同一个BFC(这个准确些吧),他们遵守执行规则第一项,依次向下排列......
.d.e我加了margin值,但是我们发现,两者中间的垂直margin并没有生效,否则应该是40px才对。
这就是执行规则2生效了。

  1. 垂直margin合并
    在CSS当中,相邻的两个盒子的外边距可以结合成一个单独的外边距。这种合并外边距的方式被称为折叠,并且因而所结合成的外边距称为折叠外边距。
    折叠的结果:
  • 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
  • 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
  • 两个外边距一正一负时,折叠结果是两者的相加的和。
  • 这个同样可以利用BFC解决。关于原理在前文已经讲过了。
    ————引用自简书苏星河

所以我们用BFC解决margin合并,如何解决呢?就是建立一个新的BFC,使得他俩没有关系。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            div {
                width: 200px;
                height: 100px;
            }
            .d {
                background-color: black;
                margin: 20px;
                display: inline-block;
            }
            .e {
                background-color: green;
                margin: 20px;
            }
        </style>
    </head>
    <body>
        <div class="d"></div>
        <div class="e"></div>
    </body>
</html>
示例二
示例二

在其中一个div的display改为inline-block,创建一个新的BFC,使得两者BFC所属不同。


浮动父容器塌陷问题
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            .wrap {
                border: solid 1px red;
                width: 250px;
            }
            .a,.b {
                width: 100px;
                height: 50px;
                background-color: orange;
                float: left;
            }
            .b {
                background-color: blue;
            }
        </style>
    </head>
    <body>
        <div class="wrap">
            <div class="a"></div>
            <div class="b"></div>
        </div>
    </body>
</html>
示例三

我是这么理解的,内部的两个div由于float,所以不在属于root BFC,则外容器内部不再有同样的BFC,判定为无内容(这里其实有歧义),所以红色框没有撑开。

从BFC的角度看解决方法


我们调整一下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            .wrap {
                border: solid 5px red;
                width: 250px;
                overflow: hidden;
            }
            .a,.b {
                width: 100px;
                height: 50px;
                background-color: orange;
                float: left;
            }
            .b {
                background-color: blue;
            }
        </style>
    </head>
    <body>
        <div class="wrap">
            <div class="a"></div>
            <div class="b"></div>
        </div>
    </body>
</html>
示例三
通过对父容器添加overflow:hidden,改变它的BFC,这样处于同样的BFC下的容器就会将子div内容算入,撑开父容器。

BFC与文字环绕
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            .ct {
                border: solid 1px black;
            }
            .aside {
                width: 50px;
                height: 50px;
                background-color: red;
                float: left;
            }
            .content {
                background-color: orange;
            }
        </style>
    </head>
    <body>
        <div class="ct">
            <div class="aside"></div>
            <div class="content">公园里还有一处烧烤区,一边看着远处耸立的高楼,一边吃着烧烤,也许脸书的员工就是喜欢这种自然田园的风光。
说实话,在硅谷这个寸土寸金的地方,脸书总部里能有这么大一块地作为公园我觉得是挺奢侈的,但是真的要比较起来,国内很多公园都比这个要做地精致和好看。连作者本人也这么觉得:</div>
        </div>
    </body>
</html>
文字盒子被挤压,文字少
文字增多

如何做到和右图一样呢?
先看看造成这个现象的原因

橙色区域为line-boxs,从表面看,文字盒子被浮动红盒子挤压到了左边,实际上,由于红盒子浮动,是新的BFC,文字盒子实际上是从父容器左边开始的,文字盒子实际上处于浮动元素的下方。文字盒子进行了移位,水平收缩为浮动元素提供了空间。
随着文字增加,文字盒子最终将会环绕在浮动元素下方,也就是现在这样。

我们如果能移动文字盒子,也就是文字的容器,就可以使它不环绕了。此处想一想W3C的概念:

In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itselfmay become narrowerdue to the floats).
在BFC中,每个盒子的左外边框紧挨着左边框的包含块(从右到左的格式化时,则为右边框紧挨)。即使在浮动里也是这样的(尽管一个盒子的边框会因为浮动而萎缩),除非这个盒子的内部创建了一个新的BFC(这种情况下,由于浮动,盒子本身将会变得更窄),

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            .ct {
                border: solid 1px black;
            }
            .aside {
                width: 50px;
                height: 50px;
                background-color: red;
                float: left;
            }
            .content {
                background-color: orange;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
        <div class="ct">
            <div class="aside"></div>
            <div class="content">公园里还有一处烧烤区,一边看着远处耸立的高楼,一边吃着烧烤,也许脸书的员工就是喜欢这种自然田园的风光。
说实话,在硅谷这个寸土寸金的地方,脸书总部里能有这么大一块地作为公园我觉得是挺奢侈的,但是真的要比较起来,国内很多公园都比这个要做地精致和好看。连作者本人也这么觉得:</div>
        </div>
    </body>
</html>

文字盒子添加overflow:hidden,使得处于新的BFC中,就不会根据上面的W3C概念规则来绘制了。


MDN——外边距合并
苏星河:【CSS】深入理解BFC原理及应用
CSS深入理解流体特性和BFC特性下多栏自适应布局
CSS布局基础:BFC
理解CSS中BFC
BFC神器背后的原理


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,737评论 1 92
  • relative:生成相对定位的元素,通过top,bottom,left,right的位置相对于其正常位置进行定位...
    zx9426阅读 933评论 0 2
  • 1.浮动元素有什么特征?对父容器、其他浮动元素、普通元素、文字分别有什么影响? 浮动元素不在文档的普通流中,它可以...
    饥人谷_Young丶K阅读 426评论 0 0
  • 一,浮动元素有什么特征?对父容器、其他浮动元素、普通元素、文字分别有什么影响? 浮动模型是一种可视化格式模型,浮动...
    DeeJay_Y阅读 862评论 0 4
  • 1.在什么场景下会出现外边距合并?如何合并?如何不让相邻元素外边距合并?给个父子外边距合并的范例 概念:在CSS当...
    饥人谷_任磊阅读 646评论 0 3