转载

CSS规范 > 9 视觉格式化模型 Visual Formatting Model

视觉格式化模型 Visual Formatting Model

URL: http://www.w3.org/TR/CSS2/visuren.html

Translator: HaoyCn

Date: 14th of Aug, 2015

本文并未全部翻译,译者在原文基础上稍有添加图示。如了解全部信息,请参看规范原版。个人水平有限,欢迎指正。

9.1 视觉格式化模型介绍

本章和下章用于描述视觉格式化模型:用户代理 User Agent 如何在视觉媒体 Visual Media 下处理文档树 Document Tree

视觉格式化模型中,文档树中的每一个元素根据盒模型 Box Model 产生零个或多个盒。这些盒的布局由以下内容控制:

  1. 盒的尺寸和类型

  2. 定位体系 Positioning Scheme (常规流,浮动和绝对定位)

  3. 文档树中元素之间的关系

  4. 外部信息(如:视口大小,图片的固有尺寸等)

本章及下章定义的属性适用于连续媒体和页面媒体 Paged Media 。然而,外边距属性的意义在页面媒体中有所不同(详情见页面模型)。

视觉格式化模型没有指定格式化的所有方面(如,没有指定字符间距算法)。本规范没有覆盖到的格式化问题上,符合规范的用户代理也可能表现不一。

9.1.1 视口 The Viewport

在连续媒体 Continuous Media 上工作的用户代理一般会向用户提供一个视口(屏幕上的一个窗口或其它可视区域)来帮助用户访问文档。用户代理可以在调整视口大小的同时改变文档的布局(见初始包含块 Initial Containing Block )。

如果视口小于渲染文档的画布区域,用户代理应提供一个滚动机制。每个画布最多有一个视口,但用户代理可以把文档渲染到多个画布上(即为相同文档提供不同视图)。

9.1.2 包含块 Containing Blocks

CSS2.1中,许多盒的定位和大小都根据一个名为包含块 Containing Block 的矩形盒的边缘来计算。一般地,生成的盒会充当其后代盒的包含块;我们称盒为其后代“创建”了包含块。说“盒的包含块”即是说“盒所处的包含块”,而不是盒所产生的包含块。

每个盒会被赋予一个相对于其包含块的位置,但它不会被局限在其包含块内;它有可能溢出。

包含块的尺寸如何计算的细节将在下章讲述。

9.2 盒的生成 Controlling Box Generation

本节描述CSS2.1中可生成的盒类型。盒的类型会影响其在视觉格式化模型中的表现。下面描述的 display 属性用来指定盒的类型。

9.2.1 块级元素 Block-level Elements 和 块盒 Block Boxes

块级元素是源文档中会被视觉格式化为块状(例:段落)的元素。 display 属性的以下值会让一个元素成为块级元素: blocklist-item 以及 table

块级盒 Block-level Boxes 是参与块格式化上下文 Block Formatting Context 的盒。每个块级元素生成一个主要的块级盒 Principal Block-level Box 来包含其后代盒和生成的内容,同时参与定位体系 Positioning Scheme 。某些块级元素还会在主要盒之外产生额外的盒: list-item 元素。这些额外的盒会相对于主要盒来摆放。

除了(下章要讲的)表格盒 Table Boxes ,和可替换元素( Replaced Elements ),一个块级盒同时也是一个块容器盒 Block Container Box ,一个块容器盒要么只包含块级盒,要么创建一个行内格式化上下文 Inline Formatting Context 并只包含行内级盒 Inline-level Boxes 。并非所有的块容器盒都是块级盒:不可替换的行内块 Bon-replaced Inline Blocks 和不可替换的表格单元格 Non-replaced Table Cells 也是块容器但不是块级盒。是块级盒、同时也是块容器的盒称作块盒 Block Boxes

这三个术语,“块级盒”、“块容器盒”、“块盒”在意义明确时可简称为“块”。

CSS规范 > 9 视觉格式化模型 Visual Formatting Model

9.2.1.1 匿名块盒

在一个如下文档中:

<div>     Some text     <p>More text</p> </div>

(假定 divp 都设置了 display: block ,) div 看起来似乎同时包含了行内类型的内容和块类型的内容。为了使界定格式化简单一些,我们假定有一个匿名块盒 Anonymous Block Box 围绕在“Some text”周围。

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

该例如图所示,有三个盒,其中一个为匿名盒。

换句话说:如果一个块容器盒(如上例中为 div 生成的盒)内有一个块级盒(如上例中的 p ),那么我们强制它只包含块级盒。

当一个行内盒 inline box 包含一个文档流内 In-flow 的块级盒,这个行内盒(及在同一行盒的 Line Box 它的行内祖先)会在该块级盒(及其连续的或者中间只被可折叠空白、脱离文档流元素分隔的块级同胞)的周围打断,把行内盒分离成两个盒(甚至一边为空也如此),各在块级盒一边。在打断之前和打断之后的行盒 Line Box 都被匿名块盒包含,并且该块级盒成为匿名块盒的同胞。当这样的行内盒受到相对定位影响,任何产生的移动同样影响到包含在其中的块级盒。

该模型将应用在下面的例子中。假设有规则如下:

p    { display: inline } span { display: block } 

被应用到如下HTML文档:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html> <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> </html>

p 元素包含一段匿名文本 C1 ,接着是一个块级元素,随后又是另一段匿名文本 C2 。结果生成了一个代表 body 的块盒,它包含了围绕 C1 一个匿名块盒、 span 的块盒,和围绕 C2 的另一个匿名块盒。

匿名盒的继承属性会从包含它的非匿名盒那里继承(比如,在子节标题“匿名块盒”下的那个例子中的 div 盒)。匿名盒的非继承属性将取其初始值。例如,匿名盒的字体属性继承自 div ,但是外边距是 0

当一个元素导致了匿名块盒的生成,则该元素上设置的属性一样能应用于该元素生成的盒和该元素的内容。例如,在上面例子中,如果在 p 元素上设置了边框,则这个边框将画在 C1 (在行的结尾开)和 C2 (在行的结尾闭)周围。

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

一些用户代理用其它方式实现了行内包含块 Inlines Containing Blocks 上的边框。例如,将其内嵌的块放入“匿名行盒”中,并在这些匿名行盒周围绘出行内边框。由于CSS1和CSS2没有定义这种表现,仅支持CSS1或CSS2的用户代理才会以其它形式来实现,并仍声称遵守这部分CSS2.1规范。对于CSS2.1规范发布之后的用户代理不会这么做。

IE6下的效果:

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

计算百分比值时,应忽略匿名块盒,而以最近的非匿名祖先盒来替代。例如,上面的 div 里,如果一个匿名块盒的子盒在需要知道其包含块的高度来获得一个百分比高度。那么它将使用 div 形成的包含块的高度,而不是匿名块盒的高度。

9.2.2 行内级元素 Inline-level Elements 和 行内盒 Inline Boxes

行内级元素是在源文档中那些不为其内容形成新的块、其内容分布在多行中的元素(如,段落内着重文本,行内图片等等)。以下的 display 属性值产生一个行内级元素: inlineinline-table ,以及 inline-block 。行内级元素生成行内级盒 Inline-level Boxes ,而这些盒会参与行内格式化上下文 Inline Formatting Context

一个行内盒是行内级盒,且其内容参与了该行内盒的行内格式化上下文。一个 display 值是 inline 的不可替换元素会生成一个行内盒。那些不是行内盒的行内级盒(例如可替换的行内级元素 Replaced Inline-level Elements 、行内块元素 inline-block 、行内表格元素 inline-table )被称为原子行内级盒 Atomic Inline-level Boxes ,因为它们以单一不透明盒的形式来参与它们的行内格式化上下文。

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

9.2.2.1 匿名行内盒 Anonymous Inline Boxes

任何被直接包含在一个块容器元素(不是包含在行内元素)的文本必须作为匿名行内元素来对待。

一个HTML文档如下:

<p>Some <em>emphasized</em> text</p>

p 产生一个块盒,其中包含了一些行内盒。 emphasized 的盒是一个由行内元素 em 生成的行内盒,但其他盒( sometext 的)是由块级元素 p 生成的行内盒。后面这种盒被称作匿名行内盒,因为它们没有相关的行内级元素。

这些匿名行内盒的可继承属性将从它们的父级块盒中继承。非继承性属性取其初始值。在上面例子中,匿名行内盒的 colorp 那里继承,但 backgroundtransparent

空白内容,根据 white-space 属性,如果可被折叠则不会产生任何匿名行内盒。

本规范中,如果可根据上下文来清晰界定一个匿名盒的类型,则匿名行内盒和匿名块盒都可被简称为匿名盒。

在格式化表格时,还会有更多类型的匿名盒出现。

9.2.3 Run-in Boxed 插入盒

为使章节号同之前的草案一致,特保留此节。 display: run-in 现已定义至CSS3(参见《CSS基本盒模型》)。

9.2.4 display 属性

(译者注:本处暂只记录常见几个值的简略介绍)

  1. block元素产生一个块盒。

  2. inline-block元素产生一个行内级块容器。行内块的内部会被当作块盒来格式化,而此元素本身会被当作原子行内级盒来格式化。

  3. inline元素产生一个或多个的行内框。

  4. none元素不出现在格式化结构中(也就是说,在视觉媒体中元素既不产生盒也不影响布局)。其后代元素也不产生任何盒:该元素及其内容会被从格式化结构中完全移除。对后代元素设定 display 属性不能覆盖这个表现。

请注意 none 值不产生可见盒;它根本就不生成盒。CSS中有使元素在格式化结构中产生盒并影响格式化,但盒本身不可见的机制。请访问visibility的章节了解详情。

除定位元素和浮动元素以及根元素外(见下文)计算值与指定值相同。根元素的计算值按下文所述改变。

注意,尽管 display 初始值是 inline ,但用户代理的默认样式表规则可能覆盖该值。请见附录中的HTML4参考样式表。

9.3 定位体系 Positioning Schemes

在CSS2.1中,盒子根据以下三种体系来布局:

  1. 常规流 Normal Flow 。CSS2.1中,常规流包括块级盒的块格式化,行内盒的行内格式化,以及块级盒和行内级盒的相对定位。

  2. 浮动 Floats 。在浮动模型中,盒首先根据常规流布局,然后从常规流中脱离并尽可能地向左或向右位移。内容可以布局在浮动周围。

  3. 绝对定位 Absolutr Positioning 。在绝对定位模型中,盒完全从常规流中脱离(对后面的同胞元素无影响)并根据包含块来分配位置。

浮动元素、绝对定位元素、根元素都被称为脱离文档流 Out of Flow ;其他元素被称为文档流内 In-flow 。元素 A 的排版流由 A 、在文档流内且最近的脱离文档流的祖先是A的元素构成。

9.3.1 选择定位体系: position 属性

(译者注:本节翻译有省略,可参考CSS手册)

  1. static:盒为常规盒,根据常规流布局, toprightbottomleft 属性不生效。

  2. relative:盒的定位根据常规流计算(盒被成为常规流内定位)。接着盒相对其常规位置移动。当B盒相对定位,B盒之后的盒定位时就当B没有移动一样来计算。 table-row-grouptable-header-grouptable-footer-grouptable-rowtable-column-grouptable-columntable-cell 以及 table-caption 上次未定义此效果。

  3. absolute:盒的位置(还可能包括大小)由 toprightbottomleft 属性指定。这些属性根据盒的包含块来规定移动。绝对定位盒脱离文档流。这意味着它们对之后的同胞盒的布局没有影响。同时,即便绝对定位盒有外边距,也不同其他任何外边距折叠。

  4. fixed:盒的定位根据 absolute 模型来计算,但除此之外,盒相对某些参照物保持固定。和 absolute 模型一样,此盒的外边距也不同其他任何外边距折叠。在手持 handheld 、投影 projection 、屏幕 screen 、打字机 tty 、电视 tv 媒体类型中,盒相对视口固定且滚动时不会移动。在打印媒体类型中,即便页面是通过视口来访问的(比如打印预览),盒也渲染在所有页,并且根据页盒固定。其他媒体类型中则未定义此表现。开发者可根据依赖媒体来指定 fixed 。比如说,如果想使盒固定在屏幕视口顶部,但不出现在打印页的顶部,这两种设定可以通过使用@media规则来分开,如下:

@media screen {   h1#first { position: fixed }  } media print {   h1#first { position: static } }

用户代理不可将固定盒的内容分页显示。注意用户代理可能用其他方法打印不可见内容。参见第13章“页盒外的内容”。

用户代理可将根元素上的 position 视为 static

9.3.2 盒位移 Box Offsets: toprightbottomleft

(译者注:本节暂略,可参考CSS手册)

9.4 常规流 Normal Flow

常规流中的盒子都属于某个格式化上下文,要么块格式化上下文,要么行内格式化上下文,总之不能二者得兼。块级盒参与块格式化上下文,行内级盒参与行内格式化上下文。

9.4.1 块格式化上下文

浮动、绝对定位元素、非块盒的块容器(如:行内块 inline-block 、表格单元格 table-cell 以及表格标题 table-caption )以及 overflow 属性不为 visible 的块盒(除了该值被传播到视口的情况)将为其内容创建一个新的块级格式化上下文。

在块格式化上下文中,盒从包含块顶部一个接一个地垂直摆放。两个同胞盒间的垂直距离取决于 margin 属性。同一个块格式化上下文中的相邻块级盒的垂直外边距将折叠。

在块格式化上下文中,每个盒的左外边缘紧贴包含块的左边缘(从右到左的格式里,则为盒右外边缘紧贴包含块右边缘),甚至有浮动也是如此(尽管盒里的行盒可能由于浮动而收缩),除非盒创建了一个新的块格式化上下文(在这种情况下盒子本身可能由于浮动而变窄)。

关于在页面媒体 Paged Media 中分页的信息,请参考允许页面分页的章节。

9.4.2 行内格式化上下文

在行内格式化上下文中,盒从包含块的顶部一个接一个地水平摆放。盒水平方向的外边距、边框和内边距在布局时都会考虑在内。盒的垂直对齐方式则不一:可能按底部或者顶部对齐,又或者按它们内容文本的基线对齐。包含了一行里所有盒的矩形区域被称为行盒 Line Box

行盒的宽度取决于包含块以及浮动。行盒的高度取决于在行盒高度计算章节所给出的规则。

行盒的高总是足以容纳其包含的所有盒。然而,它可能高于其所包含的最高盒(比如,包含的盒以基线对齐)。当一个盒( B )的高度小于包含它的行盒的高度时, B 的垂直对齐方式由 vertical-align 属性决定。当在水平方向上几个行内级盒不能完全被单个行盒包含时,它们会被分配到两个或者多个垂直摆放的行盒中。因此,一个段落就是多个行盒的垂直堆叠。行盒的堆叠没有垂直间距(除非有特别声明)并且从不重叠。

一般来说,行盒的左边缘紧贴其包含块的左边缘,其右边缘紧贴包含块的右边缘。然而,浮动盒可能被置于包含块和行盒边缘之间。因此,尽管在同一行内格式化上下文中的行盒是等宽的(包含块的宽度),由于浮动会造成可用的水平空间减少,行盒的宽度仍可能变动。同一行内格式化上下文中的行盒在高度上通常是变动的(比如,一行可能包含图片但其他行仅包含文本)。

当一行中的行内级盒的总宽度小于包含它们的包含块的时候,它们在行里的水平分布取决于 text-align 属性。如果取 justify 值,用户代理可能拉伸行内盒( inline-tableinline-block 盒除外)中的空格和字间距。

当行内盒的宽度超过行盒宽度时,行内盒将被分为多个盒,被分解出的盒则又分布在多个行盒中。如果一个行内盒不可切割(比如,行内盒包含的是单个字符或者语言指定的断字规则不允许断字,又或者行内盒的 white-space 属性值为 nowrappre ),那么该行内盒将溢出行盒。

当行内盒被分割,外边距、边框和内边距在任何断点处都不会产生视觉影响。

行内盒也可能由于双向文本处理而在一个行盒内被切割成多个盒。

为了包含行内格式化上下文中的行内级内容,行盒按需创建。有的行盒不包含文本、保留空白、外边距或内边距或边框不为零的行内元素、其他文档流内 In-flow 内容(如图片、行内块或行内表格),并且不以保留的换行符结尾,如果是为决定它们所包含的元素的定位,则必须视其为零高度的行盒,除此之外的其他目的下应视其为不存在。

下面是一个行内盒构造的例子。下属的段落(由HTML块级元素 p 创建)包含了有 emstrong 交叉的匿名文本。

<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 thissentence, dear.

或者:

Several emphasized

words appear in this

sentence, dear.

在最后这个情况里, em 盒被分割成了两个 em 盒(现称之为 split1split2 )。外边距、边框、内边距或者文本修饰在 split1 之前或者 split2 之后都没有视觉效果。

看下面这个例子:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//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 的宽度,这些盒可能分布如下:

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

  • 外边距插在了 emphasized 之前和 words 之后

  • 内边距被插在了 emphasized 之前、上、下, words 值后、上、下。虚线边框渲染在了每个单词的三边。

9.4.3 相对定位 Relative Positioning

一旦一个盒遵循常规流或者浮动而布局好位置后,它有可能根据这个位置来相对位移。这被称作相对定位。通过这种方式移动盒( B1 )对随后的盒( B2 )没有影响: B2 被赋予了一个如同 B1 没有位移的位置,并且 B2B1 移动后不会重定位。这意味着相对定位可能造成盒重叠。然而,如果相对定位造成一个 overflow:autooverflow:scroll 的盒溢出,客户端必须通过创建滚动条来让用户可以访问到该内容(在其偏移位置),这可能影响布局。

一个相对定位盒保持其常规流中的大小,包括断行和原本为其保留的空间。包含块一节解释了相对定位盒创建新的包含块的情况。

对于相对定位元素而言, leftright 在不改变盒大小的同时使其水平位移。 left 使盒向右移动, right 时期向左。 leftright 没有造成盒的分割或拉伸,因此应用的值始终满足: left = - right

如果 leftright 值均为 auto (其默认值),应用的值为 0 (即是说,盒保持在其原位)。

如果 leftauto ,其应用值为 right 的负值(即盒向左移动 right 值)。

如果 rightauto ,其应用值为 left 的负值。

如果 leftright 均不为 auto ,定位则被过度约束,其中一值必须被忽略。如果包含块的 direction 属性值为 ltr ,则 left 值胜出而 right 值改为 - left 。如果包含块的 direction 属性值为 rtlright 值胜出而 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 }

topbottom 属性在不改变相对定位元素的大小的同时使其上下位移。 top 使其下移, bottom 则使其上移。 topbottom 没有造成盒的分割或拉伸,因此应用的值始终满足: top = - bottom 。如果二者均为 auto ,其值则均为 0 。如果其中一个值为 auto ,则该属性取另一属性的负值。如果二者均不为 autobottom 将被忽略(也就是说, bottom 应用值为 top 的负值)。

注:在脚本环境中动态移动相对定位盒可以产生动画效果(见 visibility 属性)。尽管相对定位可被用于上标和下标效果,但行高在自动调整时不会将其定位纳入计算。参见行高计算一节的描述了解更多信息。

相对定位的例子将在对比常规流、浮动和相对定位一节中提供。

9.5 浮动 Floats

在当前行中一个盒被移动到左侧或右侧称为浮动。浮动最有趣的特点是内容可以布局在其旁边(或者为 clear 属性所禁止)。内容会布局在左浮动盒的右侧,或布局在右浮动盒的左侧。下述内容是对浮动定位及内容布局的介绍。控制浮动行为的准则已经在 float 属性一节中描述。

浮动盒将被移动至左侧或右侧直至其外侧紧贴包含盒的边缘或另外一个浮动的外边缘。如果存在行盒,浮动盒的顶部外边缘将与行盒的顶部对齐。

如果水平方向没有足够的空间容纳浮动,它将下移直至能够放下它或者没有其他浮动。

由于浮动不在常规流中,在浮动之前或之后创建的非定位块盒将垂直摆放,如同浮动不存在一样。然而,当前行盒和随浮动后创建的行盒会按需缩短来为浮动的外边距盒腾出空间。

当有一个垂直定位满足以下全部四个条件时,行盒将紧挨着浮动:

  1. 在行盒顶部或之下

  2. 在行盒底部或之上

  3. 在浮动的上外边距边缘之下,并

  4. 在浮动下外边距边缘之上

注:这意味着总高度 Outer Height 为零或为负的浮动不会缩短行盒。

如果行盒被缩短到不能容纳任何内容,那么行盒将下移(其宽度会重新计算)直到可以容纳内容或不再有浮动。当前行中,任何在浮动盒之前的内容将移动到同一行中的浮动的另一侧重新布局。换句话说,如果行内级盒先于左浮动被放在行盒中,而行盒的剩余空间可以容纳左浮动,那么左浮动会被置于该行内,且与行盒顶部对齐,而已经放入该行盒的行内级盒会被相应地移动到浮动的右侧(右侧即是左浮动的另一侧),反过来对 rtl 和右浮动也是这样。

表格、块级可替换元素或者在常规流中创建新的块格式化上下文的元素(如 overflow 值非 visibile 的元素),它们的边框盒不可与它们同属一个块格式化上下文中的浮动元素的外边距盒重叠。如果有必要的话,应当通过把它们置于已出现的浮动的后面达到清除浮动的效果,但如果空间足够,可以将其放置在浮动旁边。但这可能使得该元素的框盒变得比10.3.3章节定义的还要窄。CSS2没有定义用户代理何时可以把元素置于浮动旁的情况,也没有定义元素会变得多窄的情况。

举例。在下面的文档片段中,包含块不足以容纳浮动旁边的内容,因此内容需要移动到浮动下面,并根据其 text-align 属性来在行盒中定位。

p {  width: 10em;  border: solid aqua; } span {  float: left;  width: 5em;  height: 5em;  border: solid blue; }  <p>  <span> </span>  Supercalifragilisticexpialidocious </p>

该片段可能如下图所示:

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

浮动可以并列,而这个模型也适用于同一行中的并列浮动元素。

下面的规则会使所有的 class="icon"img 盒浮动到左侧(并设左外边距为 0 )。

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 元素创建的包含块之宽)。该文档格式化如下:

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

如果文档如下,格式化的结果是一样的:

<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 Context 一样堆叠起来,但定位元素、创建了新的堆叠上下文并参与了浮动的父级堆叠上下文并的元素除外。浮动可以同常规流中的其他盒重叠(比如,浮动旁边的常规流盒有负外边距的时候)。当发生重叠时,浮动会被渲染在非定位文档流内块 Non-positioned In-flow Blocks 之上,文档流内行内盒之下。

这有个例子,演示了浮动与常规流中元素的边框重叠的情况。

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

浮动图片挡住了与其重叠的块盒的边框

下一个例子演示了使用 clear 属性阻止内容布局在浮动旁边。

假设规则如下:

p { clear: left }

格式化结果可能如下所示:

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

两个段落都设置了 clear: left ,因此使得第二个段落“被往下推”到浮动之下的位置,这是“空隙”被添加到其上外边距之上的结果(见 clear 属性)

9.5.1 浮动定位: float 属性

(译者注:此处暂略,可参见CSS手册)

用户代理可以视根元素上的 floatnone

以下是控制浮动行为的准则:

  1. 左浮动盒的左外边缘不可在其包含块的左边缘之左。右浮动元素亦是。

  2. 如果当前盒左浮动,而此前源文档中已有元素生成了左浮动盒,那么对每个此前生成的盒而言,要么当前盒的左外边缘在此前生成盒的右外边缘之右,要么当前盒的顶部必须低于此前生成盒的底部。右浮动元素亦是。

  3. 左浮动盒的右外边缘不可在其旁边的右浮动盒的左外边缘之右。右浮动元素亦是。

  4. 浮动盒的上外边缘不可高于其包含块的顶部。当浮动出现两个折叠外边距之间时,浮动会如同它有一个参与常规流的空匿名父块一样来定位。该父块的位置由关于外边距折叠那章的规则规定。

  5. 浮动盒的上外边缘不可高于源文档中此前元素生成的块盒或浮动盒的上外边缘。

  6. 元素的浮动盒的上外边缘不可高于源文档中此前元素生成的盒所在的行盒的顶部。

  7. 一个左浮动盒如果有其他左浮动盒在其左侧,其右外边缘不可在其包含块的右边缘之右。(宽松点的要求是:左浮动不可超出其包含块的右边缘,除非该盒已经尽可能靠左了。)右浮动元素亦是。

  8. 浮动盒必须尽可能地往高摆放。

  9. 左浮动盒的摆放必须尽可能地靠左,右浮动盒必须尽可能靠右。更高的位置优先于更靠近左/右的位置。

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

但是在CSS2.1中,如果,在块格式化上下文中,有一个文档流内负垂直高度的外边距,使得浮动的位置高于它原本应当在的位置,所有这种负外边距被设为零,浮动的位置则未定义。

这些规则中提到的其他元素仅指:在和浮动同属一个块格式化上下文的其他元素。

这个HTML片段结果为 b 向右浮动

<p>a<span style="float: right">b</span></p>

如果 p 元素足够宽, ab 则会各执一边,如下所示:

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

9.5.2 控制浮动后的流: clear 属性

(译者注:属性介绍略,可参看CSS手册)

该属性指定元素的某侧不允许同此前的浮动盒相邻。 clear 属性不考虑其本身内的浮动或者处于其他块格式化上下文的浮动。

各值被应用于非浮动块级盒时,具有如下意义:

  1. left:要求盒的上边框边缘低于源文档内此前元素生成的左浮动盒的下外边缘。

  2. right:要求盒的上边框边缘低于源文档内此前元素生成的右浮动盒的下外边缘。

  3. both:要求盒的上边框边缘低于源文档内此前元素生成的左、右浮动盒的下外边缘。

  4. none:对盒相对于浮动的定位没有约束。

none 值可能产生空隙 Clearance 。空隙阻止外边距折叠并充当元素上外边距之上的空间。空隙被用于推动元素垂直越过浮动。

计算设置了 clear 值的元素的空隙,首先要计算元素上边框边缘的假定位置,该位置即元素 clear 属性值为 none 时实际上边框边缘应该在的位置。

如果元素上边框边缘的假定位置没有越过有关浮动,那么空隙就会产生,并且外边距折叠要根据8.3.1章规则计算。

空隙的高度被设为下述中的较大值:

  1. 块的边框边缘与要被清除的最下方的浮动的下外边缘不相交的必要高度。

  2. 将块的上边框边缘放在其假定位置的必要高度。

二选一的话,间隙高度即第一种。

注意:两种方式在目前的网页内容的兼容性上有待评估。未来的CSS规范将规定为其中一个或另一个。

注意:空隙可以为负或为零。

例1:假设(为求简单)有三个盒,规定如下: B1 块的下外边距为 M1B1 没有子元素也没有内边距和边框);浮动块 F 的高度为 HB2 块上外边距为 M2 (没有内边距或边框,没有子元素)。 B2clear 设为 both 。假设 B2 不为空。

不考虑 B2clear 属性,情况如下图所示。 B1B2 的外边距折叠。 B1 的下边框边缘处在 y = 0 的位置, F 的顶部处在 y = M1 的位置, B2 的上边框边缘处在 y = max(M1,M2) 的位置, F 的底部处于 y = M1+H 的位置。

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

同时假设 B2 不在 F 之下:

max(M1,M2)

也就是说,正如规范说明的情况,我们需要添加空隙。

我们需要两次计算空隙 C1C2 ,并取二者之大: C = max(C1,C2) 。第一种方法是把 B2 的顶部和 F 的底部齐平,即,放在 y= M1+H 。也意味着外边距之间的空隙使得外边距不再折叠:

F 的底部 = 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)

C2 = max(M1,M2) - M1 - M2

C2

又因为 C1 = H - M2,得

C2

所以

C = max(C1,C2) = C1

例2:本例中空隙的高度为负,-1em。(假设所有元素都没有边框或者内边距)

<p style="margin-bottom: 4em">  First paragraph. </p> <p style="float: left; height: 2em; margin: 0">  Floating paragraph. </p> <p style="clear: left; margin-top: 3em">  Last paragraph. </p>

说明:要是没有 clear ,首段和末段两个段落的边距将会折叠并且末段的上边框边缘将同浮动段落的顶部齐平。但 clear 使得上边框边缘低于浮动,即,下降2em。这意味着一定会产生空隙。由此,外边距不再折叠,空隙的高度 clearance 满足

clearance + margin-top = 2em

也就是说,

clearance = 2em - margin-top = 2em - 3em = -1em

clear 设在浮动元素上时,将造成浮动定位规则的修正。第10条额外规定补充如下:

  • (当 clear 设在浮动元素上时,)浮动的上外边缘必须低于所有此前左浮动盒的下外边缘( clear: left 情形下),或者低于所有此前的右浮动盒的( clear: right 情形下),或者低于此前左右浮动盒的( clear: both 情形下)。

注意:CSS1中该属性适用于所有元素,因此所有元素都能实现效果。在CSS2和CSS2.1中, clear 属性仅支持块级元素。因此开发者们应当只将此属性应用于块级元素。如果要实现行内元素清除浮动效果,不应当如上所讲的去设置空隙,而应当强制断行并插入一个或多个空行盒(或者如9.5章节所讲移动新行盒)来使要清除浮动的行内元素的行盒低于浮动盒。

9.6 绝对定位 Absolute Positioning

在绝对定位模型中,盒根据其包含块来精准位移。盒从常规流中完全脱离(对后来的同胞元素没有影响)。绝对定位盒为其常规流的子元素和绝对定位(非固定定位)后代创建新的包含块。然而,绝对定位元素的内容不在其他盒的流中。取决于重叠盒的栈级 Stack Level ,绝对定位元素的内容可能遮挡其他盒的内容(或被遮挡)。

9.6.1 固定定位 Fixed Positioning

固定定位是绝对定位的一种下属体系。唯一的区别在于,固定定位盒的包含块是由视口创建的。在连续媒体中,当文档滚动时,固定盒不移动。在此意义上,它们同固定背景图片相像。在页面媒体中,固定定位盒在每一页重复。这对布局很有用,比如,摆放每页底部的标识。比页面区域要大的固定定位盒将会被裁切。固定定位盒在初始化包含块中不可见的部分将不会打印。

开发者可以使用固定定位去创建类框架布局。考虑如下框架布局:

CSS规范 &gt; 9 视觉格式化模型 Visual Formatting Model

这可以通过如下HTML文档和样式规则实现:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html> <head> <title>A frame document with CSS 2.1</title> <style type="text/css" media="screen">  body { height: 8.5in }/* 计算百分百高度需要 */  #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>

9.7 displaypositionfloat 之间的关系

三种属性均影响盒生成及布局,它们的交互如下:

  1. 如果 display 值为 none ,那么 positionfloat 不会应用。这种情况下,元素不生成盒。

  2. 否则,如果 position 值为 absolutefixed ,盒为绝对定位, float 的计算值为 nonedisplay 的设值如下表。盒的位置由 toprightbottomleft 属性以及盒的包含块决定。

  3. 否则,如果 float 值不为 none ,盒浮动且 display 的设值如下表。

  4. 否则,如果元素为根元素, display 设值如下表,除了其在CSS2.1中未定义 list-item 的指定值是否变为计算值 blocklist-item

  5. 否则, dislay 属性值使用指定值。

对应表:

  • 指定值: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

  • 指定值:其他

  • 计算值:同指定值

正文到此结束
Loading...