Warning:
This wiki has been archived and is now read-only.
CSS2/visuren
视觉格式化模型
内容概要
- 9.1 视觉格式化模型简介
- 9.2 框的生成 Controlling box generation
- 9.2.1 块级元素和块框 Block-level elements and block boxes
- 9.2.2 行级元素和行内框 Inline-level elements and inline boxes
- 9.2.3 插入框 Run-in boxes
- 9.2.4 'display' 属性
- 9.3 定位方案Positioning schemes
- 9.4 正常排版Normal flow
- 9.4.1 块格式化上下文 Block formatting contexts
- 9.4.2 行格式化上下文 Inline formatting contexts
- 9.4.3 相对定位 Relative positioning
- 9.5 浮动 Floats
- 9.6 绝对定位 Absolute positioning
- 9.7 'display'、'position' 与 'float' 之间的关系
- 9.8 正常排版,浮动和绝对定位的对比
- 9.8.1 正常排版 Normal flow
- 9.8.2 相对定位 Relative positioning
- 9.8.3 让框浮动 Floating a box
- 9.8.4 绝对定位 Absolute positioning
- 9.9 分层的呈现 Layered presentation
- 9.10 文本方向:'direction'及'unicode-bidi'属性
介绍
本章和下一章描述了视觉格式化模型:用户端在图形媒体下如何处理文档树。
视觉格式化模型中,每一个文档树中的元素根据框模型产生零个或多个框。这些框的布局由下列内容控制:
本章和下一章中定义的属性适用于连续媒介和页面媒介。不过外边距属性的含义在应用到页面媒介时会有些不同(详细内容请参见页面模型)。
视觉格式化模型并不指定格式化的所有方面(例如,它并不指定字符间距算法)。对于这个规范没有覆盖到的格式化问题,与CSS特性保持一致的用户代理也可能有不同的表现。
视口 Viewport
在连续媒介上工作的用户代理通常会向用户提供一个视口(屏幕上的一个窗口或其它可视区域),用户可以通过它来访问文档。用户代理可以在视口被调整大小时改变文档的布局(详见初始包含块)。
如果视口小于渲染文档的画布区域,用户代理应当提供一个滚动机制。每个画布最多可拥有一个视口,但用户代理可以把文档渲染至多个画布上(即为相同文档提供不同的视图)。
包含块 Containing blocks
在CSS 2.1中,许多框的位置和大小都根据一个名为包含块的矩形框边缘来相对计算得到。为元素生成的框通常会充当其后裔框的包含块;我们称框为其后裔“创建”(establishes)了包含块。“框的包含块”表示“框所处的包含块”,而不是其产生的包含块。
每个框会被给予一个相对于其包含块的位置,但它不会被局限在其包含块内;它有可能会溢出。
框的生成 Controlling box generation
接下来的章节描述了CSS 2.1中可能产生的框的类型。在某种程度上,框的类型会影响其在视觉格式化模型中的表现。下面描述的“display”属性用来指定框的类型。
块级元素和块框 Block-level elements and block boxes
块级元素是源文件中会被格式化成块状(例:段落)的元素。'display'属性的以下取值会让一个元素成为块级元素:'block'、'list-item'、'table'。
块级框是参与块格式化上下文的框。每个块级元素生成一个主要的块级框来包含其子框和生成的内容,同时任何定位方案都会与这个主要的框有关。某些块级元素还会在主要框之外产生额外的框:例如“list-item”元素。这些额外的框会相对于主要框来放置。
除了table框,和可替换元素,一个块级框同时也是一个块容器框,一个块容器框要么只包含块级框,要么创建一个行格式化上下文而只包含行内级框。并非所有的块容器框都是块级框:不可替换的行内块和不可替换的table cell也是块容器但不是块级框。是块级框的块容器称作块框。
三个术语:块级框(block-level box)、块容器框(block container box)和块框(block box)在意义明确的时候简称为块(block)。
匿名块框 Anonymous block boxes
有这样一个文档:
<DIV>
Some text
<P>More text
</DIV>
(并假定DIV和P都设置了'display: block'),DIV似乎同时包含了行内类型的内容和块类型的内容。为了使格式化简单一些,我们假定有一个匿名块框围绕在"Some text"周围。

换句话说:如果一个块容器框(如上例中为DIV生成的框)有一个块级框(如上例中的P),那么我们强制它只包含块级框在其中。
当一个行内框包含一个属于正常排版的块级框,这个行内框(及与其位于同一行框的行内祖先)会被从周围的块级框(及其连续的块级兄弟p { display: inline }
span { display: block }
被应用到如下HTML文档:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HEAD>
<TITLE>Anonymous text interrupted by a block</TITLE>
</HEAD>
<BODY>
<P>
This is anonymous text before the SPAN。
<SPAN>This is the content of SPAN.</SPAN>
This is anonymous text after the SPAN。
</P>
</BODY>
匿名框的继承属性会从包含它的非匿名框那里继承。匿名框的非继承属性将取其初始值。例如,匿名框的字体属性继承自DIV,但是外边距是0。 当一个元素导致了匿名块框的生成,则该元素上设置的属性一样能应用于该元素生成的框和其内容之上。例如,在上面例子中,如果在P元素上设置了边框,则这个边框将画在C1(在最后一行下方开放)和C2(在第一行上方开放)周围。
一些用户代理用其它方式实现了行内包含块上的边框。例如,将其内嵌的块放入"匿名行框"中,并在这些匿名行框周围绘出行内边框。由于CSS1和CSS2没有定义这些效果,仅支持CSS1或CSS2的用户代理会以其它形式来实现,并可仍旧声称与CSS2.1的特征保持部分一致。对于CSS2.1规范发布之后才发布的用户代理,就不能再这么做了。
当处理百分比值时,应该忽略匿名块框,而以其最近的非匿名祖先框来替代。例如,如果一个匿名块框的孩子在DIV里面需要知道包含块的高度来解析一个百分比高度。那么它将使用DIV形成的包含块的高度,而不是匿名块框的高度。
行内级元素和行内框 Inline-level elements and inline boxes
行内级元素是源文档中那些不为其内容形成新的块;而让其内容分布在多行中的元素(如,段落内着重的文本,行内图形等等)。以下的'display'属性值产生一个行内级元素:'inline', 'inline-table', and 'inline-block'。行内级元素生成行内级框,而这些框会参与某个行内格式化上下文。
一个行内框是行内级框,且其内容参与了包含它的行格式化上下文。一个'display'值是'inline'的非替换元素会生成一个行内框。那些不是行内框的行级框(例如可替换的行级元素、行内块元素匿名行内框 Anonymous inline boxes
任何被直接包含在一个块容器元素(而不是行内元素)中的文本必须视为匿名行内元素。
在如下的文档中:
<P>Some <EM>emphasized</em> text</P>
P元素生成一个块框,其内还有几个行内框。"emphasized"的框是由行内元素(EM)产生的一个行内框,而其它的框("Some"和"text")是块类元素(P)产生的行内框。后者就称为匿名行内框,因为它们没有与之相关的行内级元素。
这样的行内框从其父块框那里继承可以继承的属性。非继承属性取其初始值。例子中,匿名行内框的颜色继承自P,而背景是透明的。
空格内容,如果可被折叠(根据'white-space'属性),则其不会生成任何匿名行内框。
在本规范中,如果一个匿名框的类型可根据上下文来清晰界定,则匿名行内框和匿名块框都可被简称为匿名框。
在格式化表格时,还会出现更多类型的匿名框。
插入框
[本小节存在的目的是为了让章节号码与之前的草案一致。 'display: run-in;' 的定义已移至 CSS3(请参考 CSS 基本框模型)。]
'display' 属性
'display'
取值: | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit |
初始: | inline |
適用於: | 所有元素 |
繼承: | 否 |
百分比: | (不适用) |
媒介: | 全部 |
計算值: | 见下文 |
本属性各取值的意义如下:
block
inline-block
inline
list-item
none
table、inline-table、table-row-group、table-column、table-column-group、table-header-group、table-footer-group、table-row、table-cell 与 table-caption
除了定位元素、浮动元素(请参考「'display'、'position' 与 'float' 的关系 」)与根元素,本属性的计算值与指定值相同。根元素上的本属性计算值的变动会依照「'display'、'position' 与 'float' 的关系 」中描述的规则。
请注意,尽管 'display' 的初始值是 'inline',用户代理的预设样式表可能覆盖这个值。请参考附录的 HTML4 样本样式。
p { display: block }
em { display: inline }
li { display: list-item }
img { display: none } /* 不显示图片 */
定位方案Positioning schemes
CSS 2.1 中,会根据三种定位方案来摆放框:
- 正常排版。CSS 2.1 中,正常排版包括对块级框的块格式化,对行级框的行格式化,对块级框和行级框的相对定位。
- 浮动。在浮动模型中,一个框先按照正常排版来摆放,再将它从排版流中取出并尽可能地向左或向右偏移。其它内容可以排在一个浮动的周围。
- 绝对定位。在绝对定位模型中,一个框会从排版流中完全脱离出来(它对后续的兄弟没有影响),并相对其包含块来指定其位置。
如果一个元素是浮动、绝对定位或根元素,那么它被称为排版流之外(out of flow)的元素。如果一个元素不是排版流之外的元素,那么它被称为排版流之内(in-flow)的元素。元素A的排版流包括元素A以及这么一组元素:它们是排版流之内的元素,且它们在排版流之外最近的祖先是元素A。
选择定位方案 ― 'position' 属性
'position' 属性与 'float' 属性决定了要用 CSS 2.1 的哪种定位算法来计算一个框的位置。
'position'
取值: | relative | absolute | fixed | inherit |
初始: | static |
適用於: | 所有元素 |
繼承: | 否 |
百分比: | (不适用) |
媒介: | 视觉 |
計算值: | 同指定值 |
本属性各取值的意义如下:
static
relative
absolute
fixed
@media screen {
h1#first { position: fixed }
}
@media print {
h1#first { position: static }
}
用户代理可将根元素上的 'position' 视为 'static'。
框偏移 ― 'top'、 'right' 、 'bottom' 、 'left'
本规范把 'position' 属性值不为 'static' 的元素称为定位元素。定位元素生成定位框,并根据以下四个属性来确定其摆放的位置:
'top'
取值: | <length> | <percentage> | auto | inherit |
初始: | auto |
適用於: | 定位元素 |
繼承: | 否 |
百分比: | 相对于包含块的高度 |
媒介: | 视觉 |
計算值: | 若指定值为长度,计算值为对应的绝对长度。若指定值为百分比值,计算值同指定值。否则,为'auto'。 |
该属性可以用来指定绝对定位框的上外边距边从框包含块的顶边向下偏移的距离。若用在相对定位框上,偏移量相对于框自己的顶边(也就是,用户代理在正常排版下为框分派了一个位置,再从该位置按这些属性偏移)。
'right'
取值: | <length> | <percentage> | auto | inherit |
初始: | auto |
適用於: | 定位元素 |
繼承: | 否 |
百分比: | 相对于包含块的宽度 |
媒介: | 视觉 |
計算值: | 若指定值为长度,计算值为对应的绝对长度。若指定值为百分比值,计算值同指定值。否则,为'auto'。 |
类似 'top',不过指定的是框的右外边距边从框包含块的右边向左偏移的程度。若用在相对定位框上,偏移量相对于框自己的右边。
'bottom'
取值: | <length> | <percentage> | auto | inherit |
初始: | auto |
適用於: | 定位元素 |
繼承: | 否 |
百分比: | 相对于包含块的高度 |
媒介: | 视觉 |
計算值: | 若指定值为长度,计算值为对应的绝对长度。若指定值为百分比值,计算值同指定值。否则,为'auto'。 |
类似 'top',不过指定的是框的下外边距边从框包含块的底边向上偏移的程度。若用在相对定位框上,偏移量相对于框自己的底边。
'left'
取值: | <length> | <percentage> | auto | inherit |
初始: | auto |
適用於: | 定位元素 |
繼承: | 否 |
百分比: | 相对于包含块的宽度 |
媒介: | 视觉 |
計算值: | 若指定值为长度,计算值为对应的绝对长度。若指定值为百分比值,计算值同指定值。否则,为'auto'。 |
类似 'top',不过指定的是框的左外边距边从框包含块的左边向右偏移的程度。若用在相对定位框上,偏移量相对于框自己的左边。
这四个属性的各种取值的意义如下:
auto
正常排版Normal flow
框在正常排版中必然属于一个格式化上下文,要么是块格式化上下文,要么是行格式化上下文。块级框参与块格式化上下文。行级框参与行格式化上下文。
块格式化上下文 Block formatting contexts
有这几种框会为其内容创建新的块格式化上下文:浮动框、绝对定位框、非块框的块容器在块格式化上下文中,框会从包含块的顶部开始,一个接一个地,垂直向下地摆放。两个兄弟框之间的垂直距离由 'margin' 属性来决定。在同一个块格式化上下文中,相邻的块级框之间的垂直外边距会出现折叠。
在块格式化上下文中,每个框的左外边距边要紧贴其包含块的左边。即使在有浮动的情景下也是如此,除非框创建了一个新的块格式化上下文(在这种情况下该框可能会为了避开浮动框而变窄)。
关于在页面媒体中要如何分页,请参考允许页面分页的章节。
行格式化上下文 Inline formatting contexts
在行格式化上下文中,框会从包含块的顶部开始,一个接一个地水平摆放。摆放这些框的时候,它们在水平方向上的外边距、边框、内边距所占用的空间都会被考虑在内。在垂直方向上,这些框可能会以不同形式来对齐:它们可能会把底部或顶部对齐,也可能把其内部的文本基线对齐。能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框。
行框的宽度是由包含块和存在的浮动来决定。行框的高度由行高计算这一章所描述的规则来决定。
行框一定会高到足以容纳它所包含的全部框。然而,它也可能比它所包含的最高的框还要高(例如:这些框是以基线对齐)。当框B的高度小于包含它的行框时,则B在行框中垂直对齐的位置由 'vertical-align' 属性来决定。当几个行级框在水平方向上无法塞得进同一个行框时,它们会被分布在两个或多个垂直堆放的行框中。行框会以既没有垂直间距通常,行框的左边紧贴其包含块的左边,而行框的右边紧贴其包含块的右边。然而,浮动框可以插在包含块边缘与行框边缘之间。因此,尽管在同一个行内上下文中的行框通常有同样的宽度(也就是其包含块的宽度),但它们的宽度也可能受浮动让水平可用空间减少的影响而有所改变。在同一个行格式化上下文中,行框的高度通常是变化的(例如:某一行包含了一个比较高的图片,而其它行只包含文本)。
当一行上的行级框的总宽度小于包含它们的行框的宽度,则它们在行框内的水平分布由'text-align'属性来决定。如果该属性取值为'justify',则用户代理可拉伸行内框(但不能是inline-table和inline-block框)中的空格和字间距。
当一个行内框的宽度超过了行框的宽度,则它会被分割成几个框,而这些框会分布在几个行框。如果此行内框不可分割(例如:单个字符、或语言指定的文字打断规则不允许在此行内框中出现打断、或该行内框受white-space属性为nowrap或pre的影响),那么该行内框溢出该行框。
行内框被分割的时候,外边距、边框和内边距在出现分割的地方都没有视觉效果。
取决于双向文本处理,行内框也可能在同一个行框内被分割为几个框。
行框会被按需创建来包含行格式化上下文中的行级内容。如果行框不包含文本或保留空格,不包含内外边距或边框宽度非零的行内元素,也不包含其它正常排版的内容(比如images,inline blocks或inline tables),也不以保留的换行符结尾,像这样的行框,如果是为了决定在其中任意元素的定位,则必须以零高度的行框来对待,如果为了其它的一些目的,则必须以其不存在来对待。
<P>Several <EM>emphasized words</EM> appear
<STRONG>in this</STRONG> sentence, dear.</P>
P元素产生一个块框,它包含了五个行内框,其中的三个是匿名的:
- 匿名:"Several"
- EM: "emphasized words"
- 匿名:"appear"
- STRONG: "in this"
- 匿名:"sentence, dear."
为了格式化这一段,用户代理将这五个框排入行框内。本例中,为P元素生成的框生成了行内框的包含块。如果该包含块足够宽,则这所有的行内框将放在一个行框内:
Several emphasized words appear in this sentence, dear.
否则,行内框将被分割并分布在几个行框之内。前面这一段可能被分割如下:
Several emphasized words appear
in this sentence, dear.
或者这样:
Several emphasized
words appear in this
sentence, dear.
上例中,EM框被分割为两个EM框(称为"split1"和"split2")。在split1之后或split2之前的外边距、边框、内边距和文本修饰都没有视觉上的效果。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
<HEAD>
<TITLE>Example of inline flow on several lines</TITLE>
<STYLE type="text/css">
EM {
padding: 2px;
margin: 1em;
border-width: medium;
border-style: dashed;
line-height: 2.4em;
}
</STYLE>
</HEAD>
<BODY>
<P>Several <EM>emphasized words</EM> appear here.</P>
</BODY>
</HTML>
根据P的宽度,这些框可能分配如下:

- 在"emphasized"之前和"words"之后插入了外边距。
- 在"emphasized"之前、之上和之下,在"words"之后、之上和之下插入了内边距。在每个单词的三边渲染了虚线边框。
相对定位 Relative positioning
当一个框按照正常排版或浮动来摆放好之后,它就可能相对当时的位置再有所偏移,这被称作相对定位。以这种方式使一个框(B1)发生偏移,对跟随其后的框(B2)没有影响:B2的定位就好像B1还没有偏移,并且在B1应用了偏移后B2不进行重新定位。这意味着相对定位会导致框重叠。然而,如果相对定位导致 'overflow:auto' 或 'overflow:scroll' 的框溢出,则用户代理必须允许通过创建滚动条来使用户访问到这些内容(在它的偏移后位置上),这可能会影响布局。
相对定位框保持它在正常排版下的尺寸,包括最初为其保留的换行和空白。关于包含块的章节说明了相对定位框会在何时创建一个新的包含块。
对于相对定位元素,'left'和'right'属性会在不改变其框尺寸的情况下水平地移动框。'Left'向右边移动框,并且'right'向左边移动框。框不会由于'left'或'right'属性而被分割或被拉伸,因此使用的值总是left=-right。
如果'left'和'right'值都是'auto'(它们的初始值),则其使用值就是'0'(也就是框在它们的初始位置)。
如果'left'值是'auto',则其使用值是'right'属性值的负数(也就是框通过'right'值向左移动)。
如果'right'的指定值为'auto',则其使用值是'left'属性值的负数。
如果'left'或'right'的取值都不是'auto',则对其位置的约束过多,因此要忽略其中的一个值。如果包含块的'direction'为'ltr',则'left'胜出,而'right'值变为-'left'(left的负值)。如果包含块的'direction'为'rtl',则'right'胜出,而'left'值被忽略。
div.a8 { position: relative; direction: ltr; left: -1em; right: auto }
div.a8 { position: relative; direction: ltr; left: auto; right: 1em }
div.a8 { position: relative; direction: ltr; left: -1em; right: 5em }
'top'和'bottom'属性会在不改变其框尺寸的情况下上下移动相对定位元素。'Top'把框向上移动,'bottom'把框向下移动。因为框不会由于'top'或'bottom'值而被分割或被拉伸,其使用值总是:top=-bottom。如果它们都是'auto',则它们的使用值都为'0'。如果它们中的一个是'auto',则它成为另一个的负值。如果两者都不是'auto',则'bottom'被忽略(也就是,bottom的使用值为'top'的负值)。
相对定位的例子会在对比正常排版、浮动和绝对定位的章节中提供。
浮动 Floats
在当前行向左或右偏移的框就是浮动框。浮动框最有趣的特点是其它内容可以紧挨着它的一侧来排版 (也可以通过'clear'属性来禁止这样排版)。内容会紧挨着左浮框的右侧排版,而紧挨着右浮框的左侧排版。接下来是对浮动定位和内容流的介绍。控制浮动行为的准确规则会在'float'属性的描述中提供。
一个浮动框会向左或向右进行偏移直到其外边缘紧贴其包含块的边缘或另一个浮动框的外边缘。如果摆放浮动框时,当前行已有一个行框,则浮动框的顶部外边缘会与该行框的顶部对齐。
如果因当前行剩余水平空间不足而放不下一个浮动框,则该浮动框会下移,直到找到放得下它的位置或者当前位置以下已没有更多浮动出现。
因为浮动不属于正常排版流(flow),在浮动框前面和后面被创建的非定位块框会如同该浮动不存在一样地垂直排版。但是,当前和随后的紧挨着浮动框被创建的行框,会按需要缩短其宽度来为浮动框的外边距框让出空间。
一个行框会紧挨一个浮动的前提是有某个垂直位置能满足以下四个条件:
- (a)在行框的顶部或以下;
- (b)在行框的底部或以上;
- (c)在浮动框顶外边缘以下;
- (d)在浮动框底外边缘以上。
如果被缩短后的行框过小,以至于它无法容纳任何内容,则应使该行框下移(并重新计算其可用宽度),直到它能容纳一些内容,或其下方已无其它浮动框。当前行中位于浮动框前面的任何内容要在浮动的另一边重新排版。换句话说,如果已有行级框摆放入当前行,再遇到一个左浮框可放入行框剩余的空间,则该左浮框会摆放在该行,并与行盒顶部对齐,然后之前已放入行盒内的行内框会被移到该左浮框的右边(右边算是左浮框的另一边)重新摆放。反过来对rtl和右浮动也一样。
table、块级的可替换元素,或者在正常排版流中创建了新块格式化上下文的元素p { width: 10em; border: solid aqua; }
span { float: left; width: 5em; height: 5em; border: solid blue; }
..。
<p>
<span> </span>
Supercalifragilisticexpialidocious
</p>
这片段显示出来可能像这样:

几个浮动可以是并排的,这个模型同样适用于在同一行并排的浮动。
img.icon {
float: left;
margin-left: 0;
}
考虑下面的HTML源码和样式:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML>
<HEAD>
<TITLE>Float example</TITLE>
<STYLE type="text/css">
IMG { float: left }
BODY, P, IMG { margin: 2em }
</STYLE>
</HEAD>
<BODY>
<P><IMG src=img.png alt="This image will illustrate floats">
Some sample text that has no other..。
</BODY>
</HTML>
IMG框被浮动到左边。其随后的内容会从该浮动框的同一行开始,被排版到浮动的右边。在浮动框右边的行框由于该浮动的存在而被缩短。但在浮动之后恢复它们的"正常"宽度(也就是它的由P元素创建的包含块的宽度)。该文档可能被格式化成:

如果文档像下面这样,则格式化的结果将完全相同:
<BODY>
<P>Some sample text
<IMG src=img.png alt="This image will illustrate floats">
that has no other..。
</BODY>
如章节8.3.1所说的,浮动框与其并排框的外边距绝不会发生折叠。因此,在前面的例子中,在P框和浮动的IMG框之间的垂直外边距不会折叠。
浮动框的内容会像它生成了新的堆叠上下文(stacking contexts)那样被堆叠起来,除了定位元素和创建了新的堆叠上下文并参加了其浮动的父级堆叠上下文的元素。 浮动框能与正常排版流中的其它框出现重叠(例如,当正常排版流中的框紧跟着浮动且其外边距为负值)。当重叠发生时,浮动框要绘制在正常排版的非定位块之上(front),而在正常排版的行内框之下(behine)。

一个浮动的图片遮蔽了与其重叠的块盒的边框。
下一个例子演示了使用'clear'属性去阻止内容紧挨着一个浮动。
p { clear: left }
排版效果看起来应该像这样:

两段文本都设置了 'clear: left', 这使第二段文本被推到了浮动框下边的位置 — 在其上外边距的上方插入了 "间隙" 来达到这样的效果(见 'clear' 属性)。
确定浮动的位置:'float'属性 Positioning the float: the 'float' property
'float'
取值: | right | none | inherit |
初始: | none |
適用於: | 除了章节9.7描述之外的所有元素 |
繼承: | 否 |
百分比: | (不适用) |
媒介: | 图形 |
計算值: | 同指定值 |
该属性指定一个框是应该向左或向右浮动,还是完全不浮动。它可设置在任何元素,但它只适用于生成了非绝对定位框的所有元素。该属性取值的含义如下:
left
right
none
该框不浮动。
用户代理可把根元素当作不浮动来处理。
以下是用来控制浮动效果的一些更精确的规则:
- 左浮框的左外边缘不可位于其包含块左边缘之左。对于右浮框也有类似的规则。
- 若当前框为左浮框,且在源文档中先前有元素已产生了任何左浮框,那么对于每个这样的先前框,要么当前框的左外边缘位于先前框的右外边缘之右,要么当前框的顶部必须位于先前框的底部之下。对于右浮框也有类似的规则。
- 左浮框的右外边缘不可位于其右方的任何右浮框的左外边缘之右。对于右浮框也有类似的规则。
- 浮动框的顶外边缘不可以高于其包含块的顶部。当浮动出现在两个折叠的外边距之间,则该浮动的定位就好像在排版流中插入了另一个空的父级匿名块。要按照在外边距折叠的章节中定义的规则对该父级匿名块进行定位。
- 浮动框的顶外边缘不可以高于源文档中其先前元素产生的块框或浮动框的顶外边缘。
- 浮动框的顶外边缘不可以高于源文档中其先前元素产生的框所在的行框的顶边。
- 如果一个左浮框的左方有另外一个左浮框,则其右外边缘不可位于其包含块的右边缘之右。(或者比较宽松的要求是:一个左浮动框除非它已经紧挨其包含块的左边缘,否则它不可以超出其包含快的右边缘。)对于向右浮动的元素也有类似的规则。
- 一个浮动框要放置得尽可能的高。
- 一个左浮动框必须尽量靠左放置,一个右浮动框必须尽量靠右放置。在更高的位置和更靠左或靠右的位置之间,选择前者。
在块格式化上下文中,如果浮动框有垂直外边距的取值为负数,并使该浮动框的位置在其原本的位置(假如这些垂直外边距取值为0)的上方,则CSS2.1对该浮动框的位置没有定义。
这些规则中所说的其它元素仅仅是指与浮动框在同一个块格式化上下文的其它元素。
<P>a<SPAN style="float: right">b</SPAN></P>
如果P元素有足够的宽度,则a和b将会并排,它应该看起来像:

控制跟在浮动后而的排版流:'clear'属性
'clear'
取值: | left | right | both | inherit |
初始: | none |
適用於: | 块级元素 |
繼承: | 否 |
百分比: | (不适用) |
媒介: | 图形 |
計算值: | 同指定值 |
该属性表明元素的框的哪一边不能与先前的浮动框相邻。'clear'属性不考虑在元素自身或者在其它块格式化上下文里面的浮动。
当应用于非浮动的块框时,取值的含义如下:
left
right
both
none
除了'none' 以外的值潜在地引入间隙。间隙会阻止外边距折叠,并充当一个元素上外边距之上的间隔。间隙会推动元素垂直地越过浮动。
对一个设置了'clear'属性的元素,其间隙的计算是先确定该元素上边框边的假定位置。这个位置是当元素的'clear'属性值为'none'时上边框边所在的位置。
如果元素上边框边的假定位置没有越过相关的浮动,那么引入间隙,并按 8.3.1 中的规则来进行外边距的折叠。
间隙的高度设置为以下较大者:
- 让待摆放的块框的边框边缘与位于最下方的被清除的浮动框的外边缘不出现相交时所需的最小间隔高度。
- 让待摆放的块框的顶边框边缘们于其clear为none时假定的位置时所需的间隔高度。
作为一种选择,间隙的高度可以直接等于以上第一项的高度。
不考虑B2的'clear'属性,我们有下面图表的情形。B1和B2的margin重叠。我们说B1的底border边在y=0的位置。然后,F的顶部在y=M1的位置,B2的顶border边在y=max(M1,M2),F的底部在 y = M1 + H。

我们同样假设B2不在F下面,也就是说:
在这种假设下,根据规范的描述,需要引入间隙。
要得到间隙的数值,我们首先需要使用两种计算方式计算出两个间隙,C1和C2,然后取两者中的最大值:C=max(C1,C2)。第一种方式是让B2的顶部和F的底部齐平,也就是在 y = M1 + H.那意思是,因为使用了清除它们之间的margin不再重叠:
bottom of F= top border edge of B2?
M1 + H= M1 + C1 + M2?
C1= M1 + H - M1 - M2
= H - M2
第二种计算方式是保持B2的顶部不变,也就是在 y= max(M1,M2)。 那意思是:
max(M1,M2)= M1 + C2 + M2?
C2= max(M1,M2) - M1 - M2
我们假设max(M1,M2) < M1 + H,其意味着:
C2 = max(M1,M2) - M1 - M2< M1 + H - M1 - M2 = H - M2?
C2< H - M2
且,由于C1 = H - M2,于是:
因此
例2.一个清除为负数情形下的例子,在这里清除是-1em.(假设没有元素有border和padding):
<p style="margin-bottom: 4em">
First paragraph。
<p style="float: left; height: 2em; margin: 0">
Floating paragraph。
<p style="clear: left; margin-top: 3em">
Last paragraph.
当 clear 属性设置在浮动元素上时,会导致浮动定位规则的改变。一个额外的约束(#10)被添加:
- 浮动的顶部外边必须低于所有之前的left-floating框(就'clear:left'来说)的底部外边,或者所有right-floating框(就'clear: right'来说), 或者 both ('clear: both')。
绝对定位 Absolute positioning
在绝对定位模型中,一个框基于它的包含块而显式地偏移。它完全从正常排版中脱离(对后继的兄弟没有影响)。一个绝对定位框为它的正常排版子元素和绝对地定位(不是fixed)后代生成一个新的包含块。不过,绝对定位元素的内容不会在其它框的周围排列。它们可能会也可能不会挡住另外一个框的内容(或者被挡住),这取决于互相重合的框的堆叠层次。
本规范中如果引用到一个绝对定位元素(或它的框)隐含着该元素的'position'属性设置为'absolute'或'fixed'。
固定定位 Fixed positioning
固定定位是绝对定位的一个子类。唯一的区别是,对于固定定位框,它的包含块由视口创建。对于连续媒介,固定框并不随着文档的滚动而移动。从这个意义上 说,它们类似于固定的背景图形。对于页面媒介,固定定位框在每页里重复。需要在每一页底部放置一个签名时,这个方法很有用。如果一个固定定位框的大小大于整个页面的大小,多余的部分会被裁切。

可以通过如下的HTML文档和样式表来达到这一效果:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
<HEAD>
<TITLE>A frame document with CSS2</TITLE>
<STYLE type="text/css">
BODY { height: 8.5in } /* Required for percentage heights below */
#header {
position: fixed;
width: 100%;
height: 15%;
top: 0;
right: 0;
bottom: auto;
left: 0;
}
#sidebar {
position: fixed;
width: 10em;
height: auto;
top: 15%;
right: auto;
bottom: 100px;
left: 0;
}
#main {
position: fixed;
width: auto;
height: auto;
top: 15%;
right: 0;
bottom: 100px;
left: 10em;
}
#footer {
position: fixed;
width: 100%;
height: 100px;
top: auto;
right: 0;
bottom: 0;
left: 0;
}
</STYLE>
</HEAD>
<BODY>
<DIV id="header"> ... </DIV>
<DIV id="sidebar"> ... </DIV>
<DIV id="main"> ... </DIV>
<DIV id="footer"> ... </DIV>
</BODY>
</HTML>
'display'、'position' 与 'float' 的关系 Relationships between 'display', 'position', and 'float'
影响框的生成和布局的三个属性——'display','position'和'float'——间的相互关系如下:
- 如果'display'值为'none',那么'position'和'float'无效,元素不生成框。
- 否则,如果'position'值为'absolute'或者'fixed',框绝对地定位'float'计算的值为'none',并且 display根据下面的表格进行设定。框的位置由'top', 'right', 'bottom'和'left'属性和包含块决定。
- 否则,如果'float'的值不是'none',该框是浮动的,且'display'值根据下面的表格进行设定。
- 否则,如果元素是根元素,'display'值根据下面的表格进行设定,除了其在CSS2.1里面没有定义是否指定值'list-item'对应计算值'block'或者'list-item'。
- 否则,'display' 的计算值为指定的值。
指定值 | 计算值 |
---|---|
inline-table | table |
inline, table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, table-caption, inline-block | block |
其他 | 与指定值相同 |
正常排版,浮动和绝对定位的对比 Comparison of normal flow, floats, and absolute positioning
为了演示正常排版,相对定位,浮动和绝对定位间的区别,我们提供一系列的例子,它们都基于如下的HTML片段:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
<HEAD>
<TITLE>Comparison of positioning schemes</TITLE>
</HEAD>
<BODY>
<P>Beginning of body contents。
<SPAN id="outer"> Start of outer contents。
<SPAN id="inner"> Inner contents.</SPAN>
End of outer contents.</SPAN>
End of body contents。
</P>
</BODY>
</HTML>
在文档中,我们假定有如下规则:
body { display: block; font-size:12px; line-height: 200%;
width: 400px; height: 400px }
p { display: block }
span { display: inline }
正常排版 Normal flow
考虑如下的outer和inner的CSS声明,它们并不改变正常排版框:
#outer { color: red }
#inner { color: blue }
P元素包含所有的行内内容:匿名行内文本以及两个SPAN元素。因此所有的内容将在一个行格式化内容中得到排列,包含在一个由P元素生成的包含块中,看起来如下图:

相对定位 Relative positioning
要看到相对定位的效果,我们规定:
#outer { position: relative; top: -12px; color: red }
#inner { position: relative; top: 12px; color: blue }
文本正常排列直到outer元素。outer的文本在第一行结尾排列到它的正常流向的位置和尺寸。然后包含文字行内框(分三行排列)移动了'-12px'单位(向上)。
inner的内容,作为outer的子元素,正常地应该紧接"of outer contents"排列(在第1.5行)。不过,inner的内容自身相对outer内容偏移'12px'(向下),而回到它原来的位置第二行。 注意跟随在outer之后的内容并不受outer相对定位的影响。

还要注意,如果outer的偏移是'-24px',那么outer的文本和主体文本会重合。
让框浮动 Floating a box
现在考虑浮动inner元素的效果,我们通过如下规则将它的文本向右浮动:
#outer { color: red }
#inner { float: right; width: 130px; color: blue }
文本正常排列直到inner框,它从流向中脱离并浮动到右外边距(它的'width'是显式指定的)。浮动左边的行框被缩短,文档的其余文本流入里面。

要显示'clear'属性的效果,我们在例子中加入一个兄弟元素:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
<HEAD>
<TITLE>Comparison of positioning schemes II</TITLE>
</HEAD>
<BODY>
<P>Beginning of body contents。
<SPAN id=outer> Start of outer contents。
<SPAN id=inner> Inner contents.</SPAN>
<SPAN id=sibling> Sibling contents.</SPAN>
End of outer contents.</SPAN>
End of body contents。
</P>
</BODY>
</HTML>
和如下规则:
#inner { float: right; width: 130px; color: blue }
#sibling { color: red }
这就使inner框和以前一样向右浮动,而文档的其余文本流入空出的地方:

但是,如果兄弟元素的'clear'属性设置为'right'(即,生成的兄弟框不接受在右边有浮动框相邻的位置),则兄弟的内容在浮动之下开始排列:
#inner { float: right; width: 130px; color: blue }
#sibling { clear: right; color: red }

绝对定位 Absolute positioning
最后,我们考虑绝对定位的效果。考虑如下的outer和inner的CSS声明:
#outer {
position: absolute;
top: 200px; left: 200px;
width: 200px;
color: red;
}
#inner { color: blue }
这就使outer框的顶部的定位基于它的包含块。定位框的包含块由最靠近的定位的父辈创建(或者,如果不存在这样的父辈,则采用初始包含块,就像在本例中)。outer框的顶部在包含块顶部 '200px'之下,左边在包含块左边'200px'。outer框的子框的排列相对于outer框正常排列。

下面的例子展示了一个相对定位框中的一个绝对定位的子框。尽管outer父框并没有实际偏移,设置它的'position'属性为'relative' 意味着这个框可以作为定位派生内容的包含块。由于outer框是一个行内框并跨越几行分布,第一个行内框的顶和左边(在图形中用粗点线标出)作为 'top'和'left'偏移的参考。
#outer {
position: relative;
color: red
}
#inner {
position: absolute;
top: 200px; left: -100px;
height: 130px; width: 130px;
color: blue;
}
结果可能看起来是这样的:

如果我们不定位outer框:
#outer { color: red }
#inner {
position: absolute;
top: 200px; left: -100px;
height: 130px; width: 130px;
color: blue;
}
inner框的包含块成为用初始包含块(在我们的例子中)。下面的例子展示了这种情况下。inner框最终的位置。

<P style="position: relative; margin-right: 10px; left: 10px;">
I used two red hyphens to serve as a change bar. They
will "float" to the left of the line containing THIS
<SPAN style="position: absolute; top: auto; left: -1em; color: red;">--</SPAN>
word.</P>
可能呈现为:

分层的呈现 Layered presentation
指定堆叠层次:'z-index'属性 Specifying the stack level: the 'z-index' property
'z-index'
取值: | <integer> | inherit |
初始: | auto |
適用於: | 定位元素 |
繼承: | 否 |
百分比: | N/A |
媒介: | 图形 |
計算值: | {{{7}}} |
对于一个定位框,'z-index'属性指定了:
- 当前堆叠内容中框的堆叠层次。
- 该框是否生成局部堆叠内容。
取值的含义如下:
auto
在该章节中,表达式"in front of"意思是更接近用户因为用户面对屏幕。
在CSS 2.1中,每个框在3个维度(dimensions)有个定位。除了水平和垂直的位置,框沿着"z-轴"展现并且被格式化成一个在其他的上面。当框在视觉上重叠了Z-轴定位特别地重要。这个章节谈论框怎样沿着z-轴定位。
渲染的树绘到canvas上的顺序描述是依照堆叠上下文。堆叠上下文能包含更深层的堆叠上下文。一个堆叠上下文从它的父级堆叠上下文的观点来看是原子的;在其它堆叠上下文的框可能不干涉它的任何框。
每个框属于一个堆叠上下文。每个定位的框在给出的堆叠上下文有一个整数的堆叠级别,堆叠级别是它在相同堆叠上下文里面z-轴相对于其它堆叠级别的位置。有较大堆叠级别的框总是会被格式化在较低堆叠级别框的前面。框可以有负的堆叠级别。框在同样的堆叠上下文中有同样的堆叠级别根据文档树顺序由后到前堆放。
根元素形成根堆叠上下文。其它由任意定位的元素生成(包含相对定位元素)的堆叠上下文有一个可计算的'z-index'值不同于'auto'。堆叠上下文不一定与包含块相关。在未来CSS的等级,其它属性可以引入堆叠上下文,例如'opacity'[CSS3COLOR]。
在每个堆叠上下文中,下面的层在从后到前的顺序中绘出:
- background和元素的borders形成堆叠上下文。
- 子堆叠上下文有负的堆叠级别(大多是负的在前面)。
- 属于正常排版的,非行级,非定位的后代。
- 非定位的浮动。
- 正常排版,行级,非定位后代,包含inline tables和inline块。
- 堆叠级别为0的子堆叠上下文和堆叠级别为0的定位后代。
- 子堆叠上下文有正的堆叠级别(最小的正数优先)
在每个堆叠上下文,定位元素的堆叠级数为0(第6层),非定位浮动(第4层),内联块(5层),还有inline table(5层),被渲染好像那些元素本身生成新的堆叠上下文,除了它们定位的后代和任意将是子堆叠上下文参与当前的堆叠上下文。
该渲染顺序递归地应用到每个堆叠上下文。该堆叠上下文渲染顺序的描述构成附录E详细规范定义的概述。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
<HEAD>
<TITLE>Z-order positioning</TITLE>
<STYLE type="text/css">
.pile {
position: absolute;
left: 2in;
top: 2in;
width: 3in;
height: 3in;
}
</STYLE>
</HEAD>
<BODY>
<P>
<IMG id="image" class="pile"
src="butterfly.gif" alt="A butterfly image"
style="z-index: 1">
<DIV id="text1" class="pile"
style="z-index: 3">
This text will overlay the butterfly image。
</DIV>
<DIV id="text2">
This text will be beneath everything。
</DIV>
<DIV id="text3" class="pile"
style="z-index: 2">
This text will underlay text1, but overlay the butterfly image
</DIV>
</BODY>
</HTML></span>
本例演示了透明的概念。一个框的缺省行为是允许在它后面的框透过它内容中透明的区域而可见。本例中,每个框透明地覆盖它下面的框。这一行为可以通过使用某个现成的背景属性而被重写。
文本方向:'direction'及'unicode-bidi'属性
遵照用户端不支持双向文本可以忽略'direction'和'unicode-bidi'属性在该章节描述。该例外包括用户端简单地从右至左渲染字符。因为一个系统上的字体包含它们但是不支持从右到左文本方向的概念。
在某些脚本中,文字是从右到左书写的。某些文档中,特别是以阿拉伯或希伯来文写成的文档中,以及一些溷合语言的内容中,单一(视觉上显示的)块中文字的排列也有不同的方向。这一现象称为双向排列或简称为“双向”。
Unicode标准([UNICODE],[UAX9]) 定义了一个复杂的算法来确定文字正确的方向。该算法包含了基于字符属性的隐式部分,以及对于嵌入和重写的显式控制。CSS2依赖这一算法来获得正确的双向渲染。'direction'及'unicode-bidi'属性允许作者规定文档语言的元素和属性如何与该算法相匹配。
用户端支持双向文本必须应用Unicode双向算法到每个行级框的序列且该序列不被强制(bidi class B)中断或者块外边距打断。这个序列在双向算法中形成"paragraph"(段落)单元。该段落嵌入级别通过包含块的'direction'属性的值进行设置而不是通过Unicode算法在步骤P2和P3中给出的启发式heuristic来设置。
由于文字的方向性取决于文档语言的结构和语意,在大多数情况下,这些属性应该只由文档类型描述(DTD)的设计者或特殊文档的作者使用。如果一个缺省样式表指定了这些属性,作者和用户不应该指定重写它们的规则。一个常见的例外可能是,如果一个用户端在用户的要求下将犹太语(通常以希伯来字母写成)音译为拉丁字母时,用户端重写了双向表现。
HTML 4.0规范([HTML40],8.2节)定义了HTML元素的双向排列行为。一致的HTML用户端可能在作者和用户的样式表里忽略 'direction'和'unicode-bidi'属性。在[HTML4]中指定的那些可能产生双向行为的规则出现在示例样式表中。HTML 4.0规范也包含了有关双向排列事项的更多的信息。
'direction'
取值: | rtl | inherit |
初始: | ltr |
適用於: | 所有元素,但参见描述 |
繼承: | 可 |
百分比: | N/A |
媒介: | 图形 |
計算值: | {{{7}}} |
该属性指定了块的基本书写方向,以及Unicode双向算法中嵌入和重写的方向(参见'unicode-bidi')。另外,它还规定了表格列布局的方向,水平溢出的方向,以及块设置了'text-align: justify'时,最后一个不完全的行的位置。
该属性取值的含义如下:
ltr
rtl
要使'direction'属性对行内元素有影响,'unicode-bidi'属性的值必须是'embed'或'override'。
'unicode-bidi'
取值: | embed | bidi-override | inherit |
初始: |
normal |
適用於: | 所有元素,但参见描述 |
繼承: | no |
百分比: | N/A |
媒介: | 图形 |
計算值: | {{{7}}} |
该属性取值的含义如下:
normal
embed
bidi-override
每一个块类元素的字符的最终的顺序就如同:双向控制代码如上所述加入,标记被剥离,结果的字符顺序传递给用于普通文字的Unicode双向算法实现,该实现产生和样式文本一样的分行。在这一处理中,非文字实体如图形被认为是中性字符,除非它们的'unicode-bidi'属性不是设置为 'normal'。在这一情况下,它们被认为是为该元素指定的'direction'中的重要字符。
请注意,为了能够在一个单一方向(要么全部左到右,要么全部右到左)中排列行内框,必须创建更多的行内框(包括匿名行内框),而且某些行内框在排列之前,可能必须分割或重排。 由于Unicode算法限制嵌入的层次为15层,将'unicode-bidi'设置为非'normal'的使用,必须小心,除非确定是合适的。特别地,使用'inherit'值时要特别小心。不过,对于那些一般来说显示为块的元素,更应该设置'unicode-bidi: embed',这样在显示改变到行内时,可以将元素保持在一起(见下例)。
下面的例子显示了包含双向文字的一个XML文档。它演示了一个重要的设计原则:DTD设计者应该在语言语言(元素和属性)和任何相关联的样式表中考虑双向 因素。样式表的设计应该是双向规则和其它样式表规则分离。双向规则不应该被其它样式表规则超越,从而文档语言或DTD的双向行为得以保留。
<HEBREW>
<PAR>HEBREW1 HEBREW2 english3 HEBREW4 HEBREW5</PAR>
<PAR>HEBREW6 <EMPH>HEBREW7</EMPH> HEBREW8</PAR>
</HEBREW>
<ENGLISH>
<PAR>english9 english10 english11 HEBREW12 HEBREW13</PAR>
<PAR>english14 english15 english16</PAR>
<PAR>english17 <HE-QUO>HEBREW18 english19 HEBREW20</HE-QUO></PAR>
</ENGLISH>
由于这是一个XML,样式表负责设置书写方向。样式表如下:
/* Rules for bidi */
HEBREW, HE-QUO {direction: rtl; unicode-bidi: embed}
ENGLISH {direction: ltr; unicode-bidi: embed}
/* Rules for presentation */
HEBREW, ENGLISH, PAR {display: block}
EMPH {font-weight: bold}
HEBREW元素是一个块,基本方向是右到左,ENGLISH元素是一个块,基本方向是左到右。PAR元素是块,基本方向从父元素继承。因此,前两个 PAR从右顶部开始阅读,最后的三个从左顶布开始阅读。请注意元素名选择HEBREW和ENGLISH只是为了明显表示而已;一般情况下,元素名应该反映结构而不反映语言。
EMPH元素是行内元素,而且它的'unicode-bidi'设置为'normal'(初始值),它对文字的排列没有影响。另一方面,HE-QUO元素创建一个嵌入。 如果行宽足够的长,这些文字的格式化效果可能是:
5WERBEH 4WERBEH english3 2WERBEH 1WERBEH
8WERBEH 7WERBEH 6WERBEH
english9 english10 english11 13WERBEH 12WERBEH
english14 english15 english16
english17 20WERBEH english19 18WERBEH
注意,HE-QUO嵌入使HEBREW18出现在english19之右。
如果需要分行,可能效果是:
2WERBEH 1WERBEH
-EH 4WERBEH english3
5WERB
-EH 7WERBEH 6WERBEH
8WERB
english9 english10 en-
glish11 12WERBEH
13WERBEH
english14 english15
english16
english17 18WERBEH
20WERBEH english19