常规流中的box都会存在于一个格式化上下文(formattig context)中,不同的格式化上下文决定了其内部子元素该如何排列。具体来说,块级元素会参与到块格式化上下文的布局中,行内元素会参与到行内格式化上下文的布局中。
1. 块格式化上下文(block formatting context)
在block formatting context中,框会一个接一个地被垂直放置,它们的起点是一个包含块的顶部。两个兄弟框之间的垂直距离取决于margin属性。在block formatting context中相邻的块级元素的垂直边距会折叠。
在block formatting context中,每一个元素左外边与包含块的左边相接触(对于从右到左的格式化,即direction:rtl,右外边接触包含块右边),即使存在浮动也是如此(尽管一个元素的内容区域会由于浮动而压缩),除非这个元素也创建了一个新的block formatting context。(具体例子见 css定位之浮动 一节)
浮动元素,绝对定位元素,inline-blocks,table-cells,table-captions等不是块框的块级包含框的,以及 overflow属性不是visible的元素,都创建新的块格式化上下文。
值得注意的是,block formatting context有下述重要特性有:
- 可以包含浮动元素
- 不被浮动元素覆盖
- 阻止父子元素的 margin 折叠
这就可以解释margin外边距合并那一节中的几个不合并的情况了。
2. 行内格式化上下文(inline formatting contexts)
在inline formatting contexts中,框一个接一个地水平排列,起点是包含块的顶部。水平方向上的 margin,border 和 padding 在框之间得到保留。这些行内框在垂直方向上可以以不同的方式对齐:它们的顶部或底部对齐,或根据其中文字的基线对齐,这取决与vertical-align属性。包含了这些行内框的长方形区域,会形成一行,叫做行框。行框的高度总是足够容纳其所包含的所有框。不过,它可能高于它包含的最高的框(例如,框对齐会引起基线对齐,具体可以见后面 CSS可视化格式模型之宽度、高度 中关于高度的计算部分)。当一个框 B 的高度小于包含它的行框的高度时,B 在行框中垂直方向上的对齐决定于vertical-align特性。 vertical-align 默认值为基线(baseline)对齐。
<html>
<head>
<style type="text/css">
p {background-color:silver; width:500px; }
span {border:1px solid blue; font-size:20px;vertical-align:top;}
em {border:1px solid yellow; font-size:50px;}
strong {border:1px solid red; font-size:30px;vertical-align:bottom;}
</style>
</head>
<body>
<p>
<span>span</span>
<em>em</em>
<strong>strong</strong>
</p>
</body>
</html>
如果几个行内框在水平方向无法放入一个行框内,它们可以分配在两个或多个垂直堆叠的行框中。因此,一个段落就是行框在垂直方向上的堆叠。如果一个行内框超出包含它的行框的宽度,它会被分割成几个框,并且这些框会被分布到几个行框内。如果一个行框不能被分割(例如,行内框只包含单个字符,或者语言特殊的断字规则不允许在行内框里换行,或者行内框受到带有nowrap或pre值的 white-space特性的影响,具体可以参见 CSS样式一节中关于文本的一些属性),这时,行内框会溢出行框。
<html>
<head>
<style type="text/css">
p {background-color:silver; width:100px; }
</style>
</head>
<body>
<p>
text text text texttexttexttext text text text
</p>
</body>
</html>
p元素被分割成5个行内框,且第三个行内框溢出了行框。
通常,行框的左边接触到其包含块的左边,右边接触到其 包含块的右边。然而,浮动元素可能会处于包含块边缘和行框边缘之间。总之,尽管在相同的行内格式化上下文中的行框通常拥有相同的宽度(包含块的宽度),它们中的一部分可能会因浮动元素缩短了可用宽度,在宽度上发生变化。同一行内格式化上下文中的行框通常高度不一样(如,一行包含了一个高的图形,而其它行只包含文本)。
当一行中行内框宽度的总和小于包含它们的行框的宽,它们在水平方向上的对齐,取决于text-align特性。例如把上上个例子 中p元素样式改成
p {background-color:silver; width:500px; text-align:center; }
还有一个重要的属性与行内格式化内容相关的是line-height.
对于一个包含行内元素的块元素来说,line-height指定了块内行框的最小值。再次修改上一个例子,
p {background-color:silver; width:500px; line-height:60px;}
可以看出p元素内的行框的高度变成了指定值60px,而虽然行内元素最大高度只有50px
line-height也可以指定给一个非替换行内元素,此时line-height作为该框的高度参与行框高度计算。
em {border:1px solid yellow; font-size:50px;line-height:20px;}
上图中em的以高度20px参与该框内元素高度最大值的“选拔”。
3. 相对定位
一旦一个框根据常规流布局以及浮动元素的影响得到了定位,它还可以相对该位置进行偏移。这就是相对定位。按照这种方式偏移的框不会对后续的框有影响,后面的框只会认它没偏移前的位置。这意味着偏移可能会产生框的重叠。
相对定位元素的尺寸,会保持它在常规流中的尺寸。而位移大小由left、right、top、bottom指定。如果left、right同时指定不为auto,那么如果direction=ltr的时候right值会被忽略,direction=rtl的时候left值会被忽略,如果top、bottom同时指定不为auto,那么bottom的值将被忽略。否则的话left=-right,top=-bottom。
<html>
<head>
<style type="text/css">
h2.pos_left { position:relative; left:20px; right:30px; top:20px; bottom:30px;}
h2.pos_right { position:relative; left:20px; top:20px;}
</style>
</head>
<body>
<h2>这是位于正常位置的标题</h2>
<h2>这是位于正常位置的标题</h2>
<h2 class="pos_left">这个标题设置了四个偏移</h2>
<h2 class="pos_right">这个标题设置了两个偏移</h2>
</body>
</html>
可以看出第一个相对定位元素的right、bottom属性都没有奏效。