我们在前端的学习过程中常常会遇到BFC,用BFC来解决一些margin塌陷、margin合并清理浮动流的问题
那么问题来了,我们所说的BFC到底是个什么东西呢;
什么是BFC
BFC(Block Formatting Context)即“块级格式化上下文。我来简单的解读一下:
1.块级对应单词Block,不难想到的就是display中block属性,block属性是将此元素作为块级元素显示,根据块级元素的特性进行渲染,具体的特性下文再来细说。
2.格式化Formatting,格式化这个此相信不用我细说,就是回归元素最原始的状态,即刚开始被定义时的状态。
3.上下文Content我们很熟悉,在js中上下文是一个函数执行前被定义好的的一个环境,是外部数据的集合。在这里好像还是有一点点联系的。
综合在一起就是:我们在定义块级元素,块级元素在刚刚被生成的时候(即初始化)需要规定一些规则来在浏览器上布局显示这个块级元素,这些规则也就块级元素所处的环境将成为块级元素与其他元素之间的特性。
简单来说,就是你是块级元素,浏览器在布局时有自己一套对块级元素布局的规则,身为块级元素你得按照我(浏览器)的规矩来。
那么为什么在我们在布局的时候会出现一些我们不期望的结果(如浮动脱离文档流和margin合并的问题)
慢慢来,首先就要说说BFC布局的规则是什么以及普通文档在布局是的规则又是什么?
普通文档流布局规则
1.浮动的元素是不会被父级计算高度
2.非浮动元素会覆盖浮动元素的位置
3.margin会传递给父级
4.两个相邻元素上下margin会重叠
BFC布局规则
1.浮动的元素会被父级计算高度(父级触发了BFC)
2.非浮动元素不会覆盖浮动元素位置(非浮动元素触发了BFC)
3.margin不会传递给父级(父级触发了BFC)
4.两个相邻元素上下margin会重叠(给其中一个元素增加一个父级,然后让他的父级触发BFC)
转自:https://www.cnblogs.com/CafeMing/p/6252286.html
定位方案是控制元素的布局,常见的有三种:
普通流(normal flow)
其实就是元素按照再HTML中的先后位置之上而下布局,在这个过程中,行内元素水平排列,直到当行被沾满然后换行,块级元素则会被渲染为完整的一个新行,除非另外制定,否则所有元素默认都是普通流定位,也可以说,普通六中元素的位置由该元素再HTML文档中的位置决定。
浮动(float)
在浮动布局中,元素首先按照普通流的位置出现,然后根据浮动的方向尽可能地向左边或右边偏移,其效果与印刷排版中的文本环绕相似。
绝对定位(absolute positioning)
在绝对定位布局中,元素会整体脱离普通六,因此绝对定位元素不会对其兄弟元素造成影响,而元素具体的位置由绝对定位的坐标决定。
BFC 布局规则
内部的Box会在垂直方向,一个接一个地放置。
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
BFC的区域不会与float box重叠。
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
计算BFC的高度时,浮动元素也参与计算
转自:https://blog.csdn.net/AmberWu/article/details/79543896
以上是我看的两个对流布局的理解(网上特别多,说法各有不同各有千秋)
如何触发BFC
只要元素满足下面任一条件即可触发BFC特性:
body根元素
浮动元素:float除none以外的值
绝对定位元素:position(absolute、fixed)
display为inline-block、table-cells、flex
overflow除了visible以外的值(hidden、auto、scroll)
用BFC来解决布局上的一些问题
1.margin合并
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ margin: 0; padding: 0; } .top{ width: 100px; height: 100px; background: #f00; margin-bottom:100px; } .bottom{ width: 100px; height: 100px; background: #0ff; margin-top: 200px; } </style> </head> <body> <div class="top"></div> <div class="bottom"></div> </body> </html>
可以看到两方块的上下margin只有200px,按照代码来说应该是上面的100加上下面的200,最后值为300px才对,上面的margin-bottom的100px与下面margin-top重叠了,出现了margin合并
问题出现的原因:两个块级元素处在同一个BFC环境下,同一BFC环境下的子元素margin上下会互相影响(这其实就是个bug,到我发稿为止还没完善)
解决办法:将两个元素放到不同的BFC环境下就好了,如把第二个方法bottom放到另一个bfc容器内,top中的margin-bottom是在A BFC(body)环境下的,而bottom中的margin-top实在B BFC(box)环境下的,每一个BFC都是独立的,BFC内部元素的布局不会对外部造成影响,这样一来问题就解决了。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ margin: 0; padding: 0; } .top{ width: 100px; height: 100px; background: #f00; margin-bottom:100px; } .box{ overflow: hidden;/*bfc*/ } .bottom{ width: 100px; height: 100px; background: #0ff; margin-top: 200px; } </style> </head> <body> <div class="top"></div> <div class="box"> <div class="bottom"></div> </div> </body> </html>
2.margin塌陷
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ margin: 0; padding: 0; } .outer{ width: 200px; height: 200px; background: red; margin-top: 100px; } .inner{ width: 50px; height: 50px; background: blue; margin-top:50px; } </style> </head> <body> <div class="outer"> <div class="inner"></div> </div> </body> </html>
我们想要的效果是inner盒子距离outer盒子上边距有一个50px的margin,但是实际情况是inner的margin与outer的margin重叠了,原理上与margin合并一样。
出现的原因:两个盒子处于同一个BFC环境下
解决方法:让outer盒子变成BFC元素,让里面inner单独处于一个BFC环境
.outer{ width: 200px; height: 200px; background: red; margin-top: 100px; overflow: hidden; }
3.清除浮动流
最常见的情况就是用一个div来包裹浮动元素
有浮动流的情况下下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ margin: 0; padding: 0; } .outer{ border: 2px solid black; margin:100px; } .inner{ width: 100px; height: 100px; float: left; } .red{ background: red; } .green{ background: green; } .blue{ background: blue; } </style> </head> <body> <div class="outer"> <div class="inner red"></div> <div class="inner green"></div> <div class="inner blue"></div> </div> </body> </html>
可以看的的是外面的outer并没有被内容所撑开
为什么会出现这样的情况呢
首先要先说一下什么是浮动流:浮动流是浮动元素的一种布局方式,浮动让行内元素或块元素自动转化为行内块元素。
浮动元素会脱离当前的文档流,后面出现的非浮动元素在排版时还是会按照原来的文档流来排版,所以会出现浮动元素和正常元素重叠的情况。
浮动元素脱离的只是当前的文档流,在给父级outer加margin的时候浮动元素也会跟着父级移动。
float属性在一开始的时候是为了报纸排版才产生的,所以文本类的元素能够感知到浮动流,并在浮动元素的周围排列形成文字环绕。
出现问题的原因:浮动元素处于浮动流,与普通元素所处的流层不一致,所以布局排版时是按照两个规则来布局的
解决方法:整个放到一个BFC环境下,使用同一个规则。只想要float的特性,不想要浮动流对布局的影响。
.outer{ border: 2px solid black; margin:100px; overflow: hidden; }
以上就是我对BFC的认识和对浮动流的理解,如何有什么错的地方或者是问题欢迎大家一起来讨论