一、BFC是什么
首先,先来了解一下Box 和 Formatting context把~~
Box:CSS布局的基本单位
Box: CSS布局的基本单位Box是CSS布局的对象和基本单位, 直观点来说,就是一个页面是由很多个Box组成的。元素的类型和display属性,决定了这个Box的类型。 不同类型的Box, 会参与不同的Formatting context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。
让我们看看有哪些盒子:
- block-level box: display属性为block, list-item, table的元素,会生成block-level box。并且参与block fomatting context。
- inline-level box: display属性为inline, inline-block, inline-table的元素,会生成inline-level box。并且参与inline formatting context。
- run-in box: 这个百度了一下,w3cschool就给了个定义~~后续理解了再补上把
Formatting context(格式化上下文)
格式化上下文指的是初始化元素定义的环境。包含两个要点,一个是元素定义的环境,一个是初始化。
在 CSS 中,元素定义的环境有两种,一种是块格式化上下文( Block formatting context ),另一种是行内格式化上下文( Inline formatting context )。
这两种上下文定义了在 CSS 中元素所处的环境,格式化则表明了在这个环境中,元素处于此环境中应当被初始化,即元素在此环境中应当如何布局等。
以上解释专业点的说法是:在常规流中的框,都属于一个格式化的上下文中。
什么是BFC
BFC(Block formatting context)直译为”块级格式化上下文”。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
BFC的布局规则
- 内部的Box会在垂直方向,一个接一个地放置
- Box垂直方向的距离由margin决定
- 属于同一个BFC的两个相邻Box的margin会发生重叠
- 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此
- BFC的区域不会与float box重叠
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。
- 计算BFC的高度时,浮动元素也参与计算
哪些元素会触发生成BFC
- 根元素
- float属性不为none
- position为absolute或fixed
- display为inline-block, table-cell, table-caption, flex, inline-flex
- overflow不为visible
二、BFC的作用与原理
- 自适应两栏布局
- 清楚内部浮动
- 防止垂直margin重叠
1. 自适应两栏布局
<style>
.box{
width: 500px;
position: relative;
background: yellow;
height: 500px;
}
.aside{
width: 100px;
height: 150px;
float: left;
background: pink;
}
.main{
height: 200px;
background: blue;
width: 200px;
<style>
<body>
<div class="box">
<div class="aside"></div>
<div class="main"></div>
</div>
</body>
页面展示:
根据每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此
以上代码中,box为包含块,所以尽管aside是浮动元素,是一个BFC,但是仍然与box包含块左边相接触。
而由于aside浮动了,脱离了标准流,但maindiv块仍然再标准流中,所以maindiv块会自动向上浮动,所以main块和aside块发生了重叠。
根据BFC布局规则第四条:BFC的区域不会与float box 重叠
所以我们可以把main也触发为一个BFC,这样就不会和aside这个float box 重叠拉~~
.mian{
overflow:hidden;
}
如图所示:
这样两个div块就不会重叠在一起。如果main块没有设置width的话,会根据包含块的宽度,和aside宽度,进行变大或缩小。可以动手试试~~
这里想提醒一下自己去理解一下为什么这个蓝色块不在粉色块的下面而是旁边呢 因为如果是在粉色块的外面再加一个父元素div触发其为BFC的话就会出现在下面。
我发现是我不理解清除浮动的真正目的是什么!为此我百度了一番
这里贴上一个连接作为参考 https://blog.csdn.net/u012207345/article/details/78279961
(其实这里不是很懂,aside元素设置了浮动,所以触发生成了BFC,因此是aisde元素的margin box左边与包含块border box的左边相接触把??)
百度了一下,是以上括号的那样理解的,main元素不触发BFC,这个元素会紧贴着box的左边 所以main元素和aside元素产生重叠
那么即使存在浮动也是如此是什么意思呢?
BFC布局规则有一条是BFC内外部不产生影响而显然这里的aside浮动元素是一个BFC,为了避免引起误解,所以加了一句说即使存在浮动也是如此。
其实还是有一些不理解??
所以如果main元素也触发了BFC,那么这个元素就可以不用贴着box元素的左边了。
2.清除内部浮动
.parent{
border: 5px solid #fcc;
width: 300px;
}
.child {
border: 5px solid #f66;
width: 100px;
height: 100px;
float: left;
}
<body>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
</body>
页面展示:
这里parent块没有设置高度,但子元素child块没有float的时候,parent的高度会被子元素块撑开。然鹅当子元素float后,脱离了文档标准流。就会造成高度塌陷。所以parent块就会变成一条没有高度的直线。
那么怎样才能让parent有高度呢?这就要提到清楚浮动的方法拉这个我会再写一篇文档,写完后再把链接放上来~
这里就先提BFC的解决办法把
根据BFC布局规则第六条:计算BFC的高度时,浮动元素也参与计算。
因此为达到清楚内部浮动,我们可以触发par生成BFC。那么parent块在计算自己的高度的时候,就会把浮动元素计算进去了,这样就不会产生高度塌陷了。
.parent{
overflow: hidden;
}
效果展示:
3.防止垂直margin重叠
<style>
*{
margin: 0;
padding: 0;
}
p{
color: red;
width: 200px;
height: 100px;
line-height: 100px;
text-align: center;
}
p:nth-child(1){
margin-bottom: 100px;
background: yellow;
}
p:nth-child(2){
margin-top: 100px;
background: pink;
} </style>
<body>
<p>我的第一个p段落</p>
<p>我的第二个p段落</p>
</body>
这里我把默认的margin和padding都清楚了,并且设置了p与p的margin-bottom值
可以注意到明明我给第一p设置了margin-bottom 为100px,给第二个p设置了margin-top为100px;但是很显然效果展示中两个p之间的距离只有100px,这是由于发生了margin重叠。
先把一些margin重叠的知识点放在这里把
margin重叠也就是我们常说的CSS外边距合并,W3C给出如下定义:
1.外边距合并指得是,当两个垂直外边距相遇时,它们将形成一个外边距
2.合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者。
margin产生折叠的几个条件:
- 这些margin都处于普通流中,并在同一个BFC中;
- 这些margin没有被非空内容、padding、border 或 clear 分隔开;
- 这些margin在垂直方向上是毗邻的,包括以下几种情况:
1、一个box的top margin与第一个子box的top margin
2、一个box的bottom margin与最后一个子box的bottom margin,但须在该box的height 为auto的情况下
3、一个box的bottom margin与紧接着的下一个box的top margin
4、一个box的top margin与其自身的bottom margin,但须满足没创建BFC、零min-height、零或者“auto”的height、没有普通流的子box
但是如果我们并不想让他们之间发生margin重叠呢?
根据BFC布局规则第六条:BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素
我们可以在其中一个p的外面包裹一层容器,并触发该容器生成一个BFC。那么这两个p便不属于同一个BFC,也不会发生margin重叠了。
<style>
*{
margin: 0;
padding: 0;
}
p{
color: red;
width: 200px;
height: 100px;
line-height: 100px;
text-align: center;
}
.p1{
margin-bottom: 100px;
background: yellow;
}
.wrap{
overflow: hidden;
}
.p2 {
margin-top: 100px;
background: pink;
}
</style>
<body>
<p class="p1">我的第一个p段落</p>
<div class="wrap">
<p class="p2">我的第二个p段落</p>
</div>
</body>
效果展示:
这样两个p段落之间的margin就不会发生重叠拉~~
参考:BFC神奇背后的原理
找不到原文地址了