🍎 CSS BFC 相关
# 相关概念
# 文档流
文档流分为三种:定位流、浮动流、普通流。
- 定位流:绝对定位,当元素的属性
position
为absolute
或者fixed
时,这个元素就是绝对定位元素;绝对定位的元素会脱离普通流,根据元素绝对定位的坐标决定(相关的 CSS 属性有top
、bottom
、left
、right
)- 对于
position: absolute
:元素的定位将相对于上级元素中的最近的一个position
属性为relative
/fixed
/absolute
的元素(没有则相对于body
)。 - 对于
position: fixed
:正常来说相对于浏览器的窗口定位,但是当于元素祖先的transform
属性为非none
时,会相对于该祖先进行定位。
- 对于
- 浮动流:浮动布局中,元素首先按照普通流的位置出现,然后根据浮动的方向尽可能的向左边或者右边便宜,其效果与印刷排版中的文字环绕类似。
- 普通流:FC(Format Context, 格式化上下文),是页面中的一块渲染区域,拥有一套渲染规则,决定其子元素如何布局,以及其他元素之间的关系和作用。普通流中的元素按照其 HTML 文档中的先后位置从上到下布局,其中行内元素水平排列,直到当前行被占满然后换行;块级元素会被渲染为一个完整的新行。
除非另外指定,所有元素默认都是普通流定位,普通流中元素的位置由该元素在 HTML 文档的位置决定。
# BFC 概念
引子:当在页面布局的时候,常常可能出现 元素的高度小时;两栏布局没法自适应;两个元素的间距
BFC (Block Formatting Context) ,块级格式化上下文,可以看作是一个隔离独立容器,容器中的元素不会影响外面的元素(反之亦然),是页面中的一块渲染区域,并且有一套属于自己的渲染规则(普通容器没有的一些特性)。规则如下:
- 内部的盒子会在垂直方向上一个接一个放置;
- 对于同一个 BFC 中的两个相邻的盒子的
margin
外边距会重叠,与方向无关。创建新的 BFC 可以避免外边距折叠。 - 每个元素的左外边距(外边距盒左边)与包含块的左边界(边框盒左边)相接触(从左到右,从右到左则相反),对于浮动元素也是如此。
- BFC 的区域不会与浮动元素的区域重叠;
- 计算 BFC 的高度时,浮动子元素也会参与计算;
使用 BFC 的目的是形成一个相对于外界完全独立的空间,让内部的子元素不会影响到外部的元素。(反之依然)
注意同一个元素不能同时存在于两个 BFC 中。
# BFC 的触发方式
- 根元素 (
html
元素); - 浮动的元素:
float
的值为left | right
; overflow
的值为auto | scroll | hidden
。不为visible | clip
;display
的值为 ~ (设置为inline-block | flex
等)不为flow-groot
position
的值为absolute | fixed
# BFC 的应用
🌰 例子 / 利用 BFC 实现自适应两列布局:
- 左列无固定宽度 (定宽或者不定宽都不影响)。给右列开启 BFC。、
- 将左列设置为左浮动(
float: left
),将自身的高度塌陷,其他的块级元素可以与它占据同一行的位置;- 右列为
div
块级元素,利用其自身的流特性占满整行;- 右列设置为 BFC 后(通过
overflow: hidden
)使其自身与左列的浮动元素隔离开(使得.left
和.right
不重叠),不占满整行。(利用了 BFC 浮动盒的区域不会与 BFC 重叠的特性)
🌰 例子 / 解决兄弟元素之间的 外边距发生重叠:
根据 BFC 的特性,同一个 BFC 中的块级元素的上外边距和下外边距有时候会发生重叠,其大小取其中的较大者,这就是 BFC 的外边距重叠。
同样可以利用 BFC 的这个特性,创建一个新的 BFC 就不会发生 外边距折叠。分别在两个
div
外面再包裹一层 BFC 容器(属性overflow: hidden
)。除了使用 BFC 解决这个问题,还可以规范两个元素统一使用 上外边距或者下外边距解决。
🌰 例子 / 父子元素的外边距重叠:
上面的例子中 ,父子元素均设置了上外边距(
margin-top
),并且最后子元素的上外边距没有生效,而是溢出到父元素的外面计算,即父元素本来设置的上外边距为20px
,最后被子元素溢出影响,外边距重叠取较大值,最后上外边距为30px
。解决方法,让两个元素均有各自的上外边距:
- 给父元素开启 BFC (
overflow: hidden
)- 给父元素添加
border
或者padding
。
🌰 例子 / 通过清除浮动解决父元素高度坍塌问题:
当子元素开启浮动时,子元素脱离文档流导致父元素高度只有边框部分的高度。
解决方法:给父元素开启 BFC(利用了 BFC 的特性,计算 BFC 的高度时,包括浮动的子元素)