Home > Article > Web Front-end > CSS > Translation: Understanding block-level formatting context in CSS_html/css_WEB-ITnose
Translation: Understanding block-level formatting context in CSS
Original Author: Ritesh Kumar
Original Article: http://www.sitepoint.com/understanding-block-formatting- contexts-in-cs...
Translator: HaoyCn
Date: 9th of Aug, 2015
Block Formatting Context is Part of the visual rendering of web page CSS and used to determine the layout of block boxes. It belongs to Normal Flow in the Positioning Scheme. According to W3C:
Floating, absolutely positioned elements (position is absolute or fixed), inline block elements display:inline-block, table cells display:table-cell, table titles display:table -Caption and elements whose overflow attribute value is not visible (except when the value is propagated to the window viewport) will create a new block-level formatting context.
The above quote pretty much sums up how a BFC is formed. But let's redefine it in another, more understandable way. A BFC is an HTML box that meets at least one of the following conditions:
BFC can be triggered explicitly. If we want to create it, we just need to add any of the above mentioned CSS styles to it.
For example, look at the following HTML:
<div class="container"> Some Content here</div>
A new BFC can be created by adding any necessary CSS styles to the container, such as overflow: scroll, overflow: hidden, display : flex, float: left, or display: table. Although the above conditions can create BFC, they will also produce some other effects, such as:
so whenever you want to create a BFC , we need to choose the most appropriate style based on our needs. For consistency, I use overflow: hidden in all examples in this article.
.container { overflow: hidden;}
You are free to use other styles besides overflow: hidden.
W3C specification says:
In a BFC context, the left outer side of each box is against the left side of the containing block (from In right-to-left format, the outer right side of the box is immediately adjacent to the right side of the containing block), even with floats (although the line box in the box may be narrower due to floats), unless the box creates a new BFC (In this case the box itself may be narrower due to the float).
In simple terms, as shown in the picture above, so the boxes belonging to BFC are all left aligned (in left to right format) and their left outer sides are against the containing left side of the block. In the last box we can see that although there is a floated element (brown) on the left, another element (green) is still attached to the left of the containing block. How this occurs is discussed below in the section on text wrapping.
In regular flow, boxes are placed vertically one by one starting from the top of the containing block. The vertical spacing between two sibling boxes is determined by their respective margins, but not the sum of their margins.
To make it easier to understand, let’s look at an example.
In the picture above, a red box (div) contains two sibling green elements (p), and a BFC has been created.
<div class="container"> <p>Sibling 1</p> <p>Sibling 2</p></div>
The corresponding CSS is:
.container { background-color: red; overflow: hidden; /* creates a block formatting context */}p { background-color: lightgreen; margin: 10px 0;}
Theoretically the margin between two sibling elements should be the sum of their margins (20px) but in fact it is 10px . This is known as Collapsing Margins. If sibling elements have different margins, the largest one will be used.
After discussing the above situation of BFC folding margins, it may be a bit confusing to say avoid folding now. But one thing we have to keep in mind is that vertical margins between adjacent block-level boxes (siblings) will only collapse if they are in the same BFC. If they belong to different BFCs, they will not be folded. So, by creating a new BFC we can avoid margin collapse.
Let’s add a third sibling element to our earlier example, now the HTML is:
<div class="container"> <p>Sibling 1</p> <p>Sibling 2</p> <p>Sibling 3</p></div>
The CSS is:
.container { background-color: red; overflow: hidden; /* creates a block formatting context */}p { background-color: lightgreen; margin: 10px 0;}
The result is the same as above , that is, the folding will still occur and the three siblings will be separated by a vertical distance of 10px. This is because the three p tags all belong to the same BFC.
Now we modify the third sibling element to become part of a new BFC. The HTML now becomes:
<div class="container"> <p>Sibling 1</p> <p>Sibling 2</p> <div class="newBFC"> <p>Sibling 3</p> </div></div>
CSS:
.container { background-color: red; overflow: hidden; /* creates a block formatting context */}p { margin: 10px 0; background-color: lightgreen;}.newBFC { overflow: hidden; /* creates new block formatting context */}
Now the output result is different:
Because The second and third sibling elements now belong to different BFCs, and margin collapse will not occur between them.
BFC可以包含浮动。我们经常遇到容器中含有浮动元素的情况。这种情况下容器元素没有高度并且其浮动子元素脱离了网页的常规流。我们通常用清除浮动解决这个问题,最普遍的做法就是使用伪元素。但我们也可以通过创建一个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;}
在上面这个例子中,容器没有任何高度,并且它包不住浮动子元素。为解决此问题,我们通过添加 overflow: hidden 来在容器中创建一个新的BFC。修改后的CSS成了:
.container { overflow: hidden; /* creates block formatting context */ background-color: green;}.container div { float: left; background-color: lightgreen; margin: 10px;}
现在容器可以包住浮动子元素,并且其高度会扩展至包住其子元素,在这个新的BFC中浮动元素又回归到页面的常规流之中了。
有时候浮动DIV旁边的文本会环绕它(如下图1所示)而这种情况有时候并不如我们所愿,我们想要下图2的效果。要解决这个问题,我们可以用外边距,但也可以用BFC。
首先让我们弄明白为何文字会环绕。要理解这个我们必须明白,当存在元素浮动的时候,盒模型如何工作。这就是我早先讨论BFC中对齐时候的遗留问题。我们通过下图来看图1到底发生了什么。
假设HTML是:
<div class="container"> <div class="floated"> Floated div </div> <p> Quae hic ut ab perferendis sit quod architecto, dolor debitis quam rem provident aspernatur tempora expedita. </p></div>
上图整个黑色区域表示 p 元素,如我们所见,p 元素没有移位但它叠在了浮动元素之下,而p元素的行盒子(即文本行)却移位了,行盒子水平变窄来给浮动元素腾出了空间。
随着文本的增加,最后文本将环绕在浮动元素之下,因为那时候行盒子不再需要移位,也就成了图1的样子。这就是为什么即便有浮动元素,段落仍紧贴包含块的左侧,而行盒子会变窄来给浮动元素腾位子。
如果我们能位移整个 p 元素,这个环绕问题也就迎刃而解了。
在说解决方案之前,我们再回顾下W3C规范:
在BFC上下文中,每个盒子的左外侧紧贴包含块的左侧(从右到左的格式里,则为盒子右外侧紧贴包含块右侧),甚至有浮动也是如此(尽管盒子里的行盒子 Line Box 可能由于浮动而变窄),除非盒子创建了一个新的BFC(在这种情况下盒子本身可能由于浮动而变窄)。
据此,如果 p 元素创建一个新的BFC那它就不会再紧贴包含块的左侧了。给 p 元素添加 overflow: hidden 就能轻而易举地办到。这解决了文本环绕浮动对象的问题。
如果我们创建一个占满整个容器宽度的多列布局,在某些浏览器中最后一列有时候会掉到下一行。这可能是因为浏览器四舍五入了列宽从而所有列的总宽度会超出容器。但如果我们在多列布局中的最后一列里创建一个新的BFC,它将总是占据其他列先占位完毕后剩下的空间。
我们来举个三列布局的例子:
这是HTML:
<div class="container"> <div class="column">column 1</div> <div class="column">column 2</div> <div class="column">column 3</div></div>
CSS:
.column { width: 31.33%; background-color: green; float: left; margin: 0 1%;}/* Establishing a new block formatting context in the last column */.column:last-child { float: none;overflow: hidden; }
现在尽管盒子的宽度稍有改变,但布局不会打破。当然,对多列布局来说这不一定是个好办法,但能避免最后一列下掉。这个问题上弹性盒或许是个更好的解决方案,但这个办法可以用来说明元素在这些环境下的行为。
我希望本文已经向你展示了BFC的特性以及BFC是如何影响页面上的元素的视图定位的。展示其用法的例子应该有让BFC显得更透彻一些。
如果你有任何想要补充的,请在评论里留言。如果你想更深入了解的话,一定得去回顾W3C对这个话题的详述。
本文中提及的浮动与行盒子变窄问题深入探讨,可以参看博文:http://www.zhangxinxu.com/wordpress/?p=583
转载本文亦请同时注明原出处(见本文顶部)。如您认可本文翻译,欢迎推荐或收藏,谢谢!