头图

CSS中的FC到BFC

image.png

本文首发国内开源代码托管平台Gitee
文章地址:
https://gitee.com/gooder4j/compose-hub/issues/I4U78Q

觉得不错的话,你的star是对我最大的支持!

Formatting Context简单理解,就是定义了布局规则的一片区域。它的类型包括:

  • Block Formatting Context,简称BFC
  • Inline Formatting Context,简称IFC
  • Flex Formatting Context,简称FFC
  • Grid Formatting Context,简称GFC

Block Formatting Context(BFC)

A block formatting context is a part of a visual CSS rendering of a web page. It's the region in which the layout of block boxes occurs and in which floats interact with other elements.

Block Formatting Context(BFC) 是web页面可视化CSS渲染的一部分,它是块级盒占据和float与其他元素相互作用的区域。

从定义来看,BFC是一块area、region,也就是页面上的一部分区域,这块区域上有块级盒、float,并且规定了它们的布局规则。

Formatting contexts affect layout, but typically, we create a new block formatting context for the positioning and clearing floats rather than changing the layout, because an element that establishes a new block formatting context will:

  • contain internal floats.
  • exclude external floats.
  • suppress margin collapsing.

Formatting context影响布局,但一般来说,我们会创建一个新的BFC,用于定位和清除float而不是来改变布局,因为建立了BFC的一个元素会:

  • 包含内部float
  • 排除外部float
  • 阻止外边距重叠

下面用例子展开说明上面三条规则。

BFC的三条规则

包含内部float

  1. 当一个元素没有BFC时:

image.png

HTML

<section>
    <div class="box">
        <div class="float">I am a floated box!</div>
        <p>I am content inside the container.</p>
    </div>
</section>

CSS

section {
    height: 150px;
}

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

.float {
    float: left;
    width: 200px;
    height: 100px;
    background-color: rgba(255, 255, 255, .5);
    border: 1px solid black;
    padding: 10px;
}
  1. 当元素的属性overflow不等于visible时,该元素会创建BFC:

image.png

HTML

<section>
    <div class="box">
        <div class="float">I am a floated box!</div>
        <p>I am content inside the container.</p>
    </div>
</section>
<!-- 添加新的section对比 -->
<section>
    <div class="box" style="overflow: auto;">
        <div class="float">I am a floated box!</div>
        <p>I am content inside the container.</p>
    </div>
</section>
  1. 使用display: flow-root创建BFC。

    虽然块级元素的overflow不为visibleclip时可以创建BFC,但是它有很大的缺点——偏离overflow的原意overflow是用于设定内容超出容器时的动作,如果单纯为了创建BFC而使用overflow,那么最终样式效果可能出乎意料,并且足够迷惑误导未来看这段代码的小伙伴。

    使用display: flow-root的好处:创建BFC并且不会有副作用。

image.png

HTML

<section>
    <div class="box">
        <div class="float">I am a floated box!</div>
        <p>I am content inside the container.</p>
    </div>
</section>
<section>
    <div class="box" style="overflow: auto;">
        <div class="float">I am a floated box!</div>
        <p>I am content inside the container.</p>
    </div>
</section>
<!-- 添加新的section对比 -->
<section>
    <div class="box" style="display: flow-root">
        <div class="float">I am a floated box!</div>
        <p>I am content inside the container.</p>
    </div>
</section>

排除外部float

当一个元素挨着另外一个float时:

image.png

HTML

<section>
    <div class="float">I am float</div>
    <div class="box">
        <p>Normal</p>
    </div>
</section>

CSS

section {
    height: 150px;
}

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

.float {
    float: left;
    overflow: hidden;
    margin-right: 25px;
    width: 200px;
    height: 100px;
    background-color: rgba(255, 255, 255, .75);
    border: 1px solid black;
    padding: 10px;
}

通过display: flow-root为元素加上BFC后:

image.png

阻止外边距折叠

外边距折叠指垂直方向的外边距折叠,原则上是能够折叠就折叠,主要有三种情况[3]

  1. 相邻元素外边距折叠,这是最常见的;
  2. 父元素和子孙元素没有分开(被边框、内边距、BFC等分开)是外边距也会折叠;
  3. 空元素没有内容(没有content,边框,内边距时)它的上下边距会折叠在一起。

看例子,当没有BFC时:

image.png

HTML

<div class="blue"></div>
<div class="outer">
    <div class="inner">red inner</div>
</div>

CSS

.blue {
    height: 50px;
    margin: 10px 0;
    background: blue;
}

.outer {
    background: red;
}

.inner {
    height: 80px;
    margin: 10px 0;
    background-color: coral;
}

当创建了BFC后,外边距的折叠会被阻止:

image.png

创建BFC

A block formatting context is created by at least one of the following:

  • The root element of the document (<html>).
  • Floats (elements where float isn't none).
  • Absolutely positioned elements (elements where position is absolute or fixed).
  • Inline-blocks (elements with display`: inline-block`).
  • Table cells (elements with display`: table-cell`, which is the default for HTML table cells).
  • Table captions (elements with display`: table-caption`, which is the default for HTML table captions).
  • Anonymous table cells implicitly created by the elements with display: table, table-row, table-row-group, table-header-group, table-footer-group (which is the default for HTML tables, table rows, table bodies, table headers, and table footers, respectively), or inline-table.
  • Block elements where overflow has a value other than visible and clip.
  • display: flow-root.
  • Elements with contain: layout, content, or paint.
  • Flex items (direct children of the element with display:flex or inline-flex) if they are neither flex nor grid nor table containers themselves.
  • Grid items (direct children of the element with display: grid or inline-grid) if they are neither flexnor grid nor table containers themselves.
  • Multicol containers (elements where column-count or column-width isn't auto, including elements with column-count: 1).
  • column-span: all should always create a new formatting context, even when the column-span: all element isn't contained by a multicol container (Spec change Chrome bug[4])

如下情况会创建BFC:

  • 文档的根元素(<html>
  • Float(元素的float属性值不为none)。
  • 绝对定位元素(元素的position属性值为absolute或者fix)。
  • Inline-block(元素带有display:inline-block)。
  • 表格单元(元素带有display: table-cell,它是HTML表格单元的默认属性值)。
  • 表格标题(元素带有display: table-caption,它时HTML表格标题的默认属性值)。
  • 匿名的表格单元,它会隐式地被display: table, table-row, table-row-group, table-header-group, table-footer-group(它们分别是表格、表格行、表格体、表格脚的默认属性值),inline-table所创建。
  • 块级元素的overflow属性不为visibleclip
  • display: flow-root
  • 元素有contain: layout, content或者paint
  • 本身即不是弹性容器、不是网格容器、也不是表格的Flex项目(元素带有display: flex或者inline-flex的直接子元素)。
  • 本身即不是弹性容器、不是网格容器、也不是表格的Grid项目(元素带有display: grid或者inline-grid的直接子元素)
  • 多列容器(元素的column-count或者column-width不为auto,包括column-count: 1的元素)。
  • column-span: all应该永远创建一个新的formatting context,即使column-span: all元素没有被多行容器所包括(规范改变[4],Chrome Bug[5])。

Inline Formatting Context(IFC)

Inline formatting contexts exist inside other formatting contexts and can be thought of as the context of a paragraph. The paragraph creates an inline formatting context inside which such things as <strong>, <a>, or <span> elements are used on text.

Inline formatting context 存在于其他formatting context里面,并且可以看作是paragraph的context。paragraph创建一个inline formatting context。paragraph会在用于文本的<strong><a>或者<span>的元素上创建IFC。

The box model does not fully apply to items participating in an inline formatting context. In a horizontal writing mode line, horizontal padding, borders and margin will be applied to the element and push the text away left and right. However, margins above and below the element will not be applied. Vertical padding and borders will be applied but may overlap content above and below as, in the inline formatting context, the line boxes will not be pushed apart by padding and borders.

盒模型不会完全应用于带有IFC的元素。在水平写模式线、水平内边距、边框和外边距会应用于元素上,并把文字推向左右。然鹅,元素的上边距和下边距不会被应用。垂直内边距和边框会被应用当可能覆盖上面或者下面的内容,因为在IFC中,内联盒子不会被内边距和边框所推开。

image.png

HTML

<p>Before that night—<strong>a memorable night</strong>, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact.”</p>

CSS

strong {
    margin: 20px;
    padding: 20px;
    border: 5px solid rebeccapurple;
}

Flex Formatting Context(FFC) 和 Grid Formatting Context(GFC)

除了包含内部float(因为在弹性容器或者网格容器里面不存在float子元素),其余都和BFC一样:

  1. 排除外部float
  2. 阻止外边距折叠

总结

Formatting Context可以看作是某块区域,这块区域规定了其上元素的布局规则。Formatting Context主要又4种,BFC、IFC、FFC和GFC。

其中BFC最为重要,当一块元素伴随这BFC时,会产生:

  1. 包含内部float
  2. 排除外部float
  3. 组织外边距折叠

FFC和GFC除了子孙元素没有float之外,都和BFC一样有2和3。

IFC跟内联元素效果一样,都是垂直方向外边距无效[6]

REFERENCE

[1] https://developer.mozilla.org...

[2] https://developer.mozilla.org...

[3] https://gitee.com/gooder4j/co...

[4] https://github.com/w3c/csswg-...

[5] https://bugs.chromium.org/p/c...

[6] https://gitee.com/gooder4j/co...


4 声望
0 粉丝
0 条评论
推荐阅读
事件代理——减少事件监听函数
事件代理(Event Delegation)很简单,主要是为了减少了事件监听函数的数量,通过利用事件冒泡阶段,将事件的处理放置在父元素上实现。

已注销1阅读 647

封面图
正则表达式实例
收集在业务中经常使用的正则表达式实例,方便以后进行查找,减少工作量。常用正则表达式实例1. 校验基本日期格式 {代码...} {代码...} 2. 校验密码强度密码的强度必须是包含大小写字母和数字的组合,不能使用特殊...

寒青54阅读 7.8k评论 11

JavaScript有用的代码片段和trick
平时工作过程中可以用到的实用代码集棉。判断对象否为空 {代码...} 浮点数取整 {代码...} 注意:前三种方法只适用于32个位整数,对于负数的处理上和Math.floor是不同的。 {代码...} 生成6位数字验证码 {代码...} ...

jenemy46阅读 5.9k评论 12

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木66阅读 6.1k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.3k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木43阅读 7.3k评论 6

CSS 绘制一只思否猫
欢迎关注我的公众号:前端侦探练习 CSS 有一个比较有趣的方式,就是发挥想象,绘制各式各样的图案,比如来绘制一只思否猫?思否猫,SegmentFault 思否的吉祥物,是一只独一无二、特立独行、热爱自由的(&gt;^ω^&lt...

XboxYan43阅读 2.9k评论 14

封面图
4 声望
0 粉丝
宣传栏