理解BFC

理解BFC

更好阅读体验移步:http://zhangzippo.github.io/posts/2019/04/28/_28理解bfc.html

BFC(格式化上下文)在整个css体系中是比较重要的概念,也牵扯了很多其他问题比如如浮动、定位、盒模型等,这篇文章主要帮助理解bfc的概念,特性和应用场景。

概念

先看一段来自MDN的定义:

块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。

嗯,非常严谨且官方(就是看不懂)那么我尝试用一种便于理解的方式来解释这个BFC,你可以简单的理解BFC就是页面上的一块儿区域,这个区域有一些特性,并且该区域内部有一套自己的规则不对外界元素产生干扰,是一块相对独立的渲染区域。(注意,参与BFC的是块盒子)

参考其他博客中我认为最贴切的解释:
块格式上下文是页面CSS 视觉渲染的一部分,用于决定块盒子的布局及浮动相互影响范围的一个区域。

产生这块区域需要满足以下几种条件:

  • 根元素或包含根元素的元素
  • 浮动元素(元素的 float 不是 none
  • 绝对定位元素(元素的 positionabsolutefixed
  • 行内块元素(元素的 displayinline-block
  • overflow 值不为 visible 的块元素
  • display 值为 flow-root 的元素
  • 表格单元格(元素的 displaytable-cell,HTML表格单元格默认为该值)
  • 表格标题(元素的 displaytable-caption,HTML表格标题默认为该值)
  • 匿名表格单元格元素(元素的 displaytabletable-rowtable-row-grouptable-header-grouptable-footer-group(分别是HTML table、row、tbody、thead、tfoot的默认属性)或 inline-table
  • contain值为 layoutcontentstrict 的元素
  • 弹性元素(displayflexinline-flex元素的直接子元素)
  • 网格元素(displaygridinline-grid 元素的直接子元素)
  • 多列容器(元素的 column-count不为 auto,包括 column-count1
  • column-spanall 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中。

可以看出有很多触发BFC区域的条件,其中前几个斜粗体的描述是我们经常遇到也需要重点记住的,后面的几种可以当作扩展了解就好。

这里重点说一下display:flow-root,display:flow-root是什么意思呢?它可以创建无副作用的BFC。在父级块中使用 display: flow-root 可以创建新的BFC。我们刚才分析了上面几种创造bfc的方式,但他们都是有副作用的(比如float会让元素脱离文档流靠左或靠右,position的绝对定位也会脱离文档流,overflow的值也会造成一些额外的影响),而这个值的设定是单纯创造一个BFC,没有任何其他影响,但是这个属性目前浏览器支持的不是很好,下图是这个值的兼容情况:


display: flow-root兼容情况

影响的范围

这里引用MDN的解释:

块格式化上下文包含创建它的元素内部的所有内容,但不包括创建了新BFC的子元素的内部元素。
块格式化上下文对浮动定位与清除浮动都很重要。浮动定位和清除浮动时只会应用于同一个BFC内的元素。浮动不会影响其它BFC中元素的布局,而清除浮动只能清除同一BFC中在它前面的元素的浮动。外边距折叠也只会发生在属于同一BFC的块级元素之间。
这段话的重点在于1:BFC将影响内部包含的所有内容,除非内部创建了新的子BFC区域;2:所有的BFC影响只会发生在同级次的BFC区域中。

如下面的代码,box创建了一个BFC区域,那么将影响son_1,son_1-1,son_2,由于son_自己创建了一个BFC区域,因此son_2-1将不受box的BFC影响,而只受son_2的BFC影响

<div id='box' class='BFC'>
    <div id='son_1'>
        <div id='son_1-1'></div>
    </div>
    <div id='son_2' class='BFC'>
        <div id='son_2-1'></div>
    </div>
</div>

从下图我门可以看到,外层盒子创造了一块儿BFC区域会清除浮动,第一层因为浮动的关系撑开了外层盒子,由于float:left创造了一块儿新的BFC区域,因此它的子元素的float不会撑开最外层,因此没有受到最外层BFC的影响(没有撑开第二层因为第二层给了固定高度)。这更佳说明了BFC是一块独立区域,并且内部不会影响BFC外部元素的特性。


BFC的影响范围

特性

关于以下特性介绍在css2.1规范的文档中(文章结尾文献)有相关介绍,这里前几条是翻译过来讲,后面几条是来自其他文章的总结。

特性1:在BFC中,内部块(block块级元素)从顶部开始依次垂直排列。两个同级块之间的垂直距离由“Margin”属性确定。

这个特性没什么说的,就是在BFC区域内部的子块级元素会垂直排列,这点即使不在BFC内其实也是一样的,多个div会在容器内部垂直的一个一个排列。

特性2: 内部块垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。

这个特性是指相邻的两个子块元素的相隔距离由margin决定,但并不是margin的和,而是会重叠(实际就是是margin之间的最大值),如下代码:

<div class="box">
    <div class="son">
        I am one
    </div>
    <div class="son">
        I am two
    </div>
    <div class="son">
        I am three
     </div>
</div>
<style>
.box {
  background-color: rgb(224, 206, 247);
  display:flow-root; // 创造一个BFC区域
  width:100%;
}
.son {
  width: 200px;
  height: 150px;
  background-color: white;
  border: 1px solid black;
  padding: 10px;
  margin:10px 0;
}
.son:last-child{
margin:20px 0;
}
</style>

效果如下:


image.png

可以看到每个元素之间的margin是10像素,而最后一个box与上方的box之间是20,因为margin的重叠导致了取的是两个相邻box的最大值。

特性3:每个子块元素的左外边缘接触包含块的左边缘(对于从右到左的格式,右边缘接触)。即使在存在浮动的情况下也是如此。

这里解释一下,我们知道每一个box模型是由四个层级构成的,如图:


image.png

从外到内分别是margin-box,border-box,padding-box和content-box,这个规则的意思就是说我们的子块的外边缘(也就是margin-box边缘)会与BFC区域的边缘(也就是content-box的边缘),即使在子块存在浮动的情况下也是一样的。

.box {
  background-color: rgb(224, 206, 247);
  border: 5px solid rebeccapurple;
  display:flow-root;
padding: 10px;
}
.float {
  float:left; // 添加浮动
  width: 200px;
  height: 150px;
  background-color: white;
  border: 1px solid black;
  margin:0 10px;
}

内部元素有一个10像素的margin,外部盒子有10像素的padding,内部元素的margin-box的左边与包含块content-box的做边缘接触


特性3

特性4:BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然;
这点在上面我们介绍影响范围的时候介绍过,不再做过多说明了。

特性5:计算BFC的高度时,考虑BFC所包含的所有元素,连浮动元素也参与计算
这个特性就是为何子元素浮动,如果要清除浮动可以在父元素上创造一个bfc的解释,这样高度就囊括了浮动元素。
特性6:浮动盒区域不叠加到BFC上

<div class="box"></div>
<div class="float"></div>
<style>
  .box { 
    background-color: rgb(224, 206, 247); 
    border: 5px solid rebeccapurple;
    height:100px; 
    width:100px;
    padding:10px; display:flow-root; 
  }
  .float { 
    float:left;
    height: 150px;
    background-color: white; 
    border: 1px solid black; 
    padding: 10px; 
  } 
</style>
可以看到浮动元素没有覆盖到bfc上面
浮动盒区域不叠加到BFC上

应用

1. 分属于不同的BFC时可以阻止margin重叠
根据特性2我们知道,BFC内的元素排列时margin会重叠,因此我们为了防止重叠,可以使两个元素创建自己的bfc,这样margin就不会重叠。
2. 可以包含浮动元素——清除内部浮动
根据特性五可以得知。
3. 可以阻止元素被浮动元素覆盖
根据特性六,只需要将被覆盖的元素创建成为BFC就可以解决这个问题。
4. 自适应两栏布局
我们可以利用bfc的特性来构造两栏布局:

<div class="left"></div>
<div class="right"></div>
<style>
  .left{
background:yellow;
width:200px;
height:400px;
float:left;
}
.right{
background:pink;
height:400px;
/*添加overflow:hidden,触发元素BFC*/
overflow:hidden;
}
</style>
右侧自适应两栏布局

当然我们也可以利用该特性进行3栏的布局,道理都是一样的。

这篇文章对BFC的前置概念没有过多说明,比如盒模型以及定位方案等,可以查看https://juejin.im/post/59b73d5bf265da064618731d这篇文章,本篇文章也部分参考了该文章。

参考文献

https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context
https://www.w3.org/TR/CSS21/visuren.html#block-formatting
https://juejin.im/post/59b73d5bf265da064618731d

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

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,725评论 1 92
  • BFC 的全称是 Block Formating Context,译为“块级格式化上下文”,是 CSS 规范中的一...
    柏丘君阅读 306评论 0 0
  • 深入理解BFC与IFC 正常的流中就是如何把文档中的元素呈现出来 ,而布局呈现的规则就是BFC、IFC和相对位移,...
    moyi_gg阅读 4,918评论 2 1
  • 一、什么是BFC Formatting context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一...
    浪里行舟阅读 653评论 0 3
  • 本来是计划重读李笑来的专栏,但是在阅读过程中,我发现自己一个很大的问题:一字不落的读完后,发觉自己的大脑没怎么吸收...
    阳光小鹿530阅读 248评论 0 3