-
Notifications
You must be signed in to change notification settings - Fork 3
Description
背景
前段时间做了个小活动的页面,页面很简单,很快也做完了,当然不知道那天脑子是不是抽了,一个浮动的元素让我很费解,其实之前做业务也遇到过浮动元素,当然清除浮动的方法有很多,什么overflow:hidden啊,clearfix啊都可以,但是突然我意识到,一直用这些属性,可是为什么设置了这些属性,它就能清除浮动呢?带着这个疑问,我决定搞清楚这个里面的门道。
overflow
关于overflow,MDN的定义是:
- The overflow property specifies whether to clip content, render scrollbars, or display overflowing content when it is too large for its block-level container.
常见的overflow的value:
// Content is not clipped
overflow: visible;
// Content is clipped, with no scrollbars
overflow: hidden;
// Content is clipped, with scrollbars
overflow: scroll;
// Let the browser decide
overflow: auto;
// Global values
overflow: inherit;
overflow: initial;
overflow: unset;
关于overflow的常见的属性,Chris Coyier在css-tricks上写过一篇比较简单通俗的文章《The CSS Overflow Property》可以看看,这里不做详述。
BFC
当我在看overflow时,看到了通过overflow:hidden属性可以清除浮动,这不是大家都知道的嘛~但是突然一个名词映入我的眼帘:block formatting context,乍一看怎么这么不顺眼,再细看,原来就是BFC啊,以前面试不是被问过么,但是当时只知道记住是什么,具体原理好像也不理解,我就在想这overflow和BFC有啥关系啊,既然如此,那咱就好好来看看这BFC到底是什么鬼。
关于BFC,依旧看一下MDN的定义:
- A block formatting context is a part of a visual CSS rendering of a Web page. It is the region in which the layout of block boxes occurs and in which floats interact with each other.
- 块格式化上下文(block formatting context) 是Web页面的可视CSS渲染的一部分。它是块盒子的布局发生及浮动体彼此交互的区域。
然后我就懵逼了,这是什么?说了半天我也没明白,好吧,还是来看看W3C的定义吧:
- Floats, absolutely positioned elements, inline-blocks, table-cells, table-captions, and elements with ‘overflow’ other than ‘visible’ (except when that value has been propagated to the viewport) establish new block formatting contexts.
- 浮动,绝对定位元素,inline-blocks, table-cells, table-captions,和overflow的值不为visible的元素,(除了这个值已经被传到了视口的时候)将创建一个新的块级格式化上下文。
看完这个定义后,相信大家还是稍微有点了解了BFC是个什么东西了吧?大概能猜到这个BFC是和float。overflow这些属性相关的,也就是说和我之前说的浮动元素肯定是有关联的,好,顺着这个方向,我们继续研究BFC相关内容。
MDN中解释满足下列情况便会创建BFC:
- the root element or something that contains it
- floats (elements where float is not none)
- absolutely positioned elements (elements where position is absolute or fixed)
- inline-blocks (elements with display: inline-block)
- table cells (elements with display: table-cell, which is the default for HTML table cells)
- table captions (elements with display: table-caption, which is the default for HTML table captions)
- block elements where overflow has a value other than visible
- display: flow-root
高清无码翻译来了:
- 根元素或其它包含它的元素
- 浮动 (元素的 float 不是 none)
- 绝对定位的元素 (元素具有 position 为 absolute 或 fixed)
- 内联块 inline-blocks (元素具有 display: inline-block)
- 表格单元格 (元素具有 display: table-cell,HTML表格单元格默认属性)
- 表格标题 (元素具有 display: table-caption, HTML表格标题默认属性)
- 块元素具有overflow ,且值不是 visible
- display: flow-root
创建BFC
只要符合上述其中一种情况,一个BFC就可以被很简单的创建,下面我们简单地建立一个BFC:
<div class="container">
Some Content here
</div>
通过给上述class为container添加符合BFC要求的任何一个属性,都可以让该div成为一个BFC,如overflow: scroll,overflow: hidden,display: flex,float: left等等。
但是,有些属性可能会存在一些问题:
display:table:可能在响应方面会产生一些问题overflow:scroll:可能会显示不必要的滚动条float:left:将会把元素置于容器的左边,其他元素环绕着它overflow:hidden:将会剪切掉溢出的元素
根据实际情况,可以选择不同的方式去建立所需要的BFC。
BFC中的box怎么对齐?
可能会有人有疑问了,BFC中设置了这些特殊的属性会不会对里面的正常流布局以及对齐方式产生影响,下面我们就这个问题,简单讨论一下。
W3C官方的解释如下:
In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).
在BFC中,每个盒子的左外边框紧挨着包含块的左边框(从右到左的格式,则为紧挨右边框)。即使存在浮动也是这样的(尽管一个盒子的边框会由于浮动而收缩),除非这个盒子的内部创建了一个新的BFC浮动,盒子本身将会变得更窄)

简单来说,在上图中我们可以看到,所有属于同一个BFC的盒子都左对齐(左至右的格式),他们的左外边框紧贴着包含块的左边框。在最后一个盒子里我们可以看到尽管那里有一个浮动元素(棕色)在它的左边,另一个元素(绿色)仍然紧贴着包含块的左边框。关于为什么会发生这种情况的原理将会在下面进行讨论。
BFC与浮动的关系?
谈了很多,终于回归到主题了,一开始我们的出发点就是为了研究为什么一个小小的属性就能清除浮动,下面我们来看看BFC与浮动的关系。
在我们日常开发的时候经常会碰到这种情况,一个容器里有浮动元素,但容器元素没有高度,它的浮动元素将会脱离页面的常规流。我们通常使用清除浮动来解决这个问题,最受欢迎的方法是使用一个clearfix的伪类元素。但我们同样可以通过定义一个BFC来达到这个目的。
举个栗子:
<div class="container">
<div>Sibling</div>
<div>Sibling</div>
</div>
对应CSS
.container {
background-color: green;
}
.container div {
float: left;
background-color: lightgreen;
margin: 10px;
}
以上例子中,父容器的高度为0,它将无法包含已经浮动的子元素。为了解决这个问题,我们通过添加overflow: hidden,在容器中创建一个新的BFC。经过修改过的CSS为:
.container {
overflow: hidden; /* creates block formatting context */
background-color: green;
}
.container div {
float: left;
background-color: lightgreen;
margin: 10px;
}
这样一个BFC块就成功将浮动元素包裹在里面了,在这个BFC中,这些元素将会回到页面的常规文档流。
见:https://codepen.io/SitePoint/pen/eNyxZB/
总结
本文主要从浮动这一普通现象一步步发散,探寻了BFC的原理,以及通过BFC来清除浮动的原理,当然BFC还有更多有用的特性,欢迎大家补充和更新。

