关于css:你所不知道的BFC

概述

BFC即Block Formatting Context。依据MDN上的定义,它是web页面上CSS可视化渲染的一部分,代表了一个渲染区域,块级元素在此区域中布局、浮动元素在此区域中与其它元素相互作用。
艰深了解它是页面布局规定中的一小套规定,是页面整体布局中的mini布局。BFC是一个容器,容器中依照肯定的规定进行布局,不会影响容器之外的其它元素。BFC容器的产生具备肯定的条件,BFC是CSS布局的基石。

一. 触发生成BFC的条件

根元素(<html>,能够解释页面上失常流中block元素的行为了)
浮动元素(元素的 float 属性不是 none)
相对定位元素(元素的 position属性 为 absolute 或 fixed)
行内块元素(元素的 display 属性为 inline-block)
• 表格单元格(元素的 display 属性为 table-cell,HTML表格单元格默认为该值)
• 表格题目(元素的 display属性 为 table-caption,HTML表格题目默认为该值)
• 匿名表格单元格元素(元素的 display 为 table、table-row、 table-row-group、table-header-group、table-footer-group(别离是HTML table、row、tbody、thead、tfoot 的默认属性)或 inline-table)
overflow 计算值(Computed)不为 visible 的块元素
display 值为 flow-root 的元素
• contain 值为 layout、content 或 paint 的元素
• 弹性元素(display 为 flex 或 inline-flex 元素的间接子元素)
• 网格元素(display 为 grid 或 inline-grid 元素的间接子元素)
• 多列容器(元素的 column-count 或 column-width (en-US) 不为 auto,包含 column-count 为 1)
• column-span 为 all 的元素始终会创立一个新的BFC,即便该元素没有包裹在一个多列容器中(规范变更,Chrome bug)

二. BFC中的布局规定

  1. Box会在垂直方向,一个接一个地搁置;
  2. Box垂直方向的间隔由margin决定。属于同一个BFC的两个相邻Box的margin会产生合并,如后文中的图4;
  3. 在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格局来说,则触碰到右边缘);
  4. 对于浮动元素:BFC的区域不会与浮动盒子产生交加,而是紧贴浮动边缘;计算BFC的高度时,也会检测浮动或者定位的盒子高度。

三. 利用BFC能够做什么

1. 父容器蕴含浮动元素时高度产生塌陷

<div class="outer">
    <div class="float">我是一个左浮动元素.</div>
     此处是文本,文本的数量多得足够突围浮动的图片的话,边框将能够框住整体
</div>
.outer {
    border: 5px dotted rgb(214,129,137); border-radius: 5px;width: 450px;padding: 10px;margin-bottom: 40px;
}
.float {
    padding: 10px;border: 5px solid rgba(214,129,137,.4);border-radius: 5px;background-color: rgba(233,78,119,.4); color: #fff;float: left; width: 200px;margin: 0 20px 0 0;
}

图1-文本够多,高度可突围浮动元素:

图2-文本少了,高度产生坍塌:

为什么会呈现高度塌陷呢?
是因为当把元素设置为浮动之后,它就脱离了失常的文档流,此时因为容器outer没有设置高度,导致高度以其失常流中的文字高度为准。浮动元素与容器边框产生重叠。
有哪些解决办法呢?
1.利用CSS的hack:革除浮动;
2.利用本文中的BFC,把容器outer触发成为一个BFC,利用它能够包裹浮动元素的个性。

.outer {
    border: 5px dotted rgb(214,129,137);border-radius: 5px;width: 450px;padding: 10px;margin-bottom: 40px;
    /*解决办法 2:overflow: auto; 或者 display:flow-root;*/
    }
    /*解决办法 1:设置不可见的伪元素,革除浮动 */
.outer:after {
    visibility: hidden;display: block;content: "";clear: both;height: 0;
}

图3:

2. 垂直方向上外边距合并

先看一段代码,领会下什么是外边距合并。能够看到,当为两个段落都设置为10px的高低外边距时,p1、p2之间理论只有一个10px,并非20px。另外,如果不将container生成BFC,则p1段落的上外边距也是不失效的,它会与div齐全重叠,如图4。

<div class="container">
    <p>我是container中的p1段落</p>
    <p>我是container中的p2段落</p>
</div>
.container {
    background-color: #ccc;
}
p { 
    background-color: rgb(233,78,119); 
    margin: 10px 0; 
}

图4:
比照图4中的两个差别,能够看到将container转变为BFC区域后,p1、p2的高低外边距失效。
为了了解同一个BFC中的外边距会产生合并,增加一个p3,并将它置于不同的BFC之中,从图5能够看到,此时,p3与p2之间即为失常的间隔20px。由此也能够阐明,BFC蕴含了它所含有的所有元素,但不包含创立了新BFC的子元素的外部元素。即人不可能同时踏入两条河流,BFC也一样,一个元素不可能同时属于两个BFC。

<div class="container">
    <p>我是container中的p1段落</p>
    <p>我是container中的p2段落</p>
    <div class="newBFC">
        <p>我是container中的p3段落</p>
    </div>
</div>
.container {
    background-color: #ccc;
    overflow: hidden;/* 将父容器设置为BFC */
}
p { 
    background-color: rgb(233,78,119); 
    margin: 10px 0; 
}  
.newBFC {
    overflow: hidden; /* 创立一个新的BFC */
}

图5:

3. 自适应两栏布局的创立

后面的图1展现了文本包裹浮动元素的状况,如何设置文本不在突围浮动,从而实现一个两栏布局呢?利用BFC,很容易实现。

<div class="outer">
        <div class="float">我是一个左浮动元素.</div>
        <div class="txt">此处是文本,将我设置为一个BFC,我就不再突围浮动元素了,我本人玩本人的去咯~~~</div>
    </div>
.txt{
    border: 5px solid rgba(214,0,0,.4);
    border-radius: 5px;
    overflow: hidden; /* 创立一个新的BFC */
}

图6:

四. BFC与文档流、布局的关系

通过下面的剖析,能够看出BFC在页面布局特地是块级元素布局是非常重要的。那么BFC与文档流又是什么关系呢?文档流即normal flow,是页面中元素显示的规定,通过position属性和float属性,能够将元素从文档流脱离,造成定位流和浮动流。
normal流其实就是指FC(Formatting Context),直译过去是格式化上下文。FC它是页面中的一块CSS渲染区域,有一套渲染规定,决定了其子元素如何布局,以及和其余元素之间的关系和作用。常见的FC有BFC、IFC(Inline Formatting Contexts),还有GFC(GridLayout Formatting Contexts)和FFC(Flex Formatting Contexts)。

小结

本文首先概述了BFC的具体含意,并列出了如何能够造成BFC的办法,而后介绍了BFC区域的布局规定,并应用例子的形式重点介绍了利用BFC进行页面布局时能够解决的问题:浮动元素导致的高度塌陷、外边距合并问题以及自适应两栏布局的实现。最初还拓展介绍了BFC的兄弟、与页面布局中文档流的关系。CSS知识点比拟杂散,抓住重点、逐个击破。加油~

参考文章:
understanding-css-layout-block-formatting-context
Block_formatting_context from MDN
BFC神奇背地的原理

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理