定位方案控制元素的布局,在 CSS 2.1 中,有三种定位方案——普通流 (Normal Flow) 、浮动 (Floats) 和绝对定位 (Absolute Positioning) 。
在普通流中,元素按照其在 HTML 中的先后位置至上而下布局。
除非另外指定,否则所有元素默认都是普通流定位,也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。
在浮动布局中,元素首先按照普通流的位置出现,然后根据浮动的方向尽可能的向左边或右边偏移,其效果与印刷排版中的文本环绕相似。
在绝对定位布局中,元素会整体脱离普通流,因此绝对定位元素不会对其兄弟元素造成影响(如果看了上文的童鞋,会发现这点与浮动元素会影响兄弟元素是不同的),而元素具体的位置由绝对定位的坐标决定。
Formatting Contexts,是页面中的一块渲染区域,并有自己的一套渲染规则,它决定了其子元素如何定位,以及和其他元素的关系和相互作用。
块格式化上下文(block formatting context,BFC) 是页面 CSS 视觉渲染这个过程中的一个概念。它是决定块盒子的布局及浮动元素相互影响的一个因素。这个概念决定了该如何渲染元素。
在定位体系中它属于普通流。
下列情况将创建一个BFC:
在块格式化上下文中,框会从包含块的顶部开始,一个接一个地,垂直向下地摆放。
两个兄弟框之间的垂直距离由 ‘margin’ 属性来决定。在同一个块格式化上下文中,相邻的块级框之间的垂直外边距会出现折叠。
在块格式化上下文中,每个框的左外边距边要紧贴其包含块的左边。即使在有浮动的情景下也是如此,除非框创建了一个新的块格式化上下文。
从整体上看,BFC 是隔离了的容器,这个具体可以表现为三个特性:
一般情况下,两个相连的 div 在垂直上的外边距会发生叠加。
但,仅当两个块级元素相邻并且在同一个BFC中时,它们垂直方向之间的外边距才会叠加。也就是说,即便两个块级元素相邻,但当它们不在同一个块级格式化上下文时它们的边距也不会折叠。
因此,阻止外边距折叠只需产生新的 BFC 。
<div class="container">
<p>Sibling 1p>
<p>Sibling 2p>
<p>Sibling 3p>
div>
.container {
background-color: red;
overflow: hidden; /* creates a block formatting context */
}
p {
background-color: lightgreen;
margin: 10px 0;
}
此时三个子元素在一个BFC中,因此会产生垂直外边距合并的状况:
现在让我们来修改第三个兄弟元素使得它属于另一个新的BFC。它的HTML将变为:
<div class="container">
<p>Sibling 1p>
<p>Sibling 2p>
<div class="newBFC">
<p>Sibling 3p>
div>
div>
.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 */
}
此时由于第三个子元素和前两个子元素不属于同一个BFC,因此它的外边距不会和第二个元素的合并:
一个BFC可以包含浮动。
很多时候我们会碰到这种情况,一个容器里有浮动元素。由于这个原因,容器元素没有高度,它的浮动孩子将会脱离页面的常规流。我们通常使用清除浮动来解决这个问题,最受欢迎的方法是使用一个clearfix的伪类元素。但我们同样可以通过定义一个BFC来达到这个目的。
<div class="container">
<div>Siblingdiv>
<div>Siblingdiv>
div>
.container {
background-color: green;
}
.container div {
float: left;
background-color: lightgreen;
margin: 10px;
}
在上面的这个案例中,父容器将不会有任何的高度,它将不会包含已经浮动的子元素。
为了解决这个问题,我们通过添加overflow: hidden,在容器中创建一个新的BFC。
(原来overflow:hidden清除浮动的原理是这个!!!才知道!!)
经过修改过的CSS为:
.container {
overflow: hidden; /* creates block formatting context */
background-color: green;
}
.container div {
float: left;
background-color: lightgreen;
margin: 10px;
}
在BFC中,每个盒子的左外边框紧挨着包含块的左边框(从右到左的格式,则为紧挨右边框)。即使存在浮动也是这样的,除非这个盒子的内部创建了一个新的BFC浮动。
简单来说,如上图所示,所有属于BFC的盒子都左对齐(在从左到右的格式下)并且它们的左外侧紧贴包含块的左侧。
在最后一个盒子中我们可以看到尽管左侧存在一个浮动元素(棕色),另外一个元素(绿色)仍然紧贴包含块的左侧。这种情况就会造成我们所说的文字环绕的效果。
可以看到浮动元素叠加到另一个元素上,另一个元素的文本内容形成了环绕浮动元素的效果。
为了解决这个问题,我们不想让浮动元素和未浮动元素相互叠加。而由于在一个BFC中所有元素的左侧都和容器左边界对齐。根据这些,如果为这个p元素创建一个新的BFC,那么它将不会紧挨着容器块的左边缘。这个可以通过简单的给p元素添加overflow: hidden来实现。这个方法创建了一个新的BFC解决了文字环绕在浮动元素周围的问题。
如果我们创建一个占满整个容器宽度的多列布局,在某些浏览器中最后一列有时候会掉到下一行。这可能是因为浏览器四舍五入了列宽从而所有列的总宽度会超出容器。但如果我们在多列布局中的最后一列里创建一个新的BFC,它将总是占据其他列先占位完毕后剩下的空间。
<div class="container">
<div class="column">column 1div>
<div class="column">column 2div>
<div class="column">column 3div>
div>
.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;
}
现在尽管盒子的宽度稍有改变,但布局不会打破。当然,对多列布局来说这不一定是个好办法,但能避免最后一列下掉。这个问题上弹性盒或许是个更好的解决方案,但这个办法可以用来说明元素在这些环境下的行为。
内联格式化上下文(Inline Formatting Contexts),是内联元素渲染和排列的规则。
当元素的 CSS 属性 display 的计算值为 inline, inline-block 或 inline-table 时,称它为行内级元素,IFC会起作用。
IFC有以下规则:
IFC有什么作用呢?
参考资料:
CSS > 译文:理解CSS中的块级格式化上下文