1. 概念
在视觉格式化模型中,文档树中的每一个元素都将会根据盒模型产生零到多个盒子。这些盒子的布局由以下因素决定:
- 盒子的尺寸和类型
- 定位策略(正常文档流,浮动或者绝对定位)
- 和文档树中其余元素的关系
- 额外的信息(好比视口的大小,图片的原始尺寸等)
1.1 视口(viewport)
连续媒体(continuous media)的UA(user agent/用户代理)一般会给用户提供一个视口,通常为一个窗口或者屏幕上的一片可视区域。用户经过这个视口查看文档(document)。当视口的大小改变时,UA可能会改变文档的布局。
当视口的大小比文档所渲染的区域(画布,canvas)小时,UA须要提供滚动机制。每一个画布只能有至多一个视口,可是UA能够将一个文档渲染到多个画布上去(好比提供同一个文档的不一样展现方式)。
1.2 包含块
在CSS2.1中,许多盒子的位置和大小都是根据一个叫作包含块(containing block)的长方形盒子的边进行计算的。一般,生成的盒子做为后代盒子的包含块,也就是说一个盒子产生它后台盒子的包含块。“盒子的包含块”指的是包含盒子的包含块,而不是盒子产生的包含块。
每一个盒子都根据它的包含块进行定位,但并不会受包含块限制,它可能溢出(overflow)
2. 控制盒子的生成
下面几节描述了CSS2.1中可能产生的盒子的类型。在视觉格式化模型中,盒子的类型会部分的影响盒子的行为。在CSS2.1中,能够经过"display"属性指定盒子的类型。
2.1 块级元素和块级盒子
块级元素(Block-level element)就是在那些源文档中被格式化成可见的块的元素,好比段落。"display"属性的以下取值将会把元素变成块级元素:"block"、"list-item"和"table"。
块级盒子(Block-level box)就是那些在块格式化上下文(block formatting context)中的盒子。每一个块级元素都会产生一个主块级盒子。这个主块级盒子包含后代盒子和其余生成的内容,同时还参与任何的定位策略。有些块级元素,除了主块级盒子之外,还将产生其余的盒子,如"list-item"元素。这些额外的盒子将根据主块级盒子进行布局。
除了表盒子和可替代的元素盒子,块级盒子一般也是块容器盒子(block container box)。一个块容器盒子既能够仅包含块级盒子,又能够创建一个行内格式化上下文,从而包含行级盒子。并非全部的块容器盒子都是块级盒子,不可替代的行内块以及不可替代的表格单元都是块容器盒子,但他们都不是块级盒子。那些是块容器盒子的块级盒子被叫作块盒子(block box)。
当上下文含义清晰的时候,块级盒子、块容器盒子和块盒子有时被简称为块。
2.2 行级元素和行内盒子
行级元素就是那些源文档中不会致使新块的产生的元素,元素的内容分布在行内。例如段落的强调文字部分、行内图片等。"display"属性的以下属性值指定一个元素为行级元素:"inline"、"inline-table"和"inline-block"。行级元素产生行级盒子,这些行级盒子存在于行内格式化上下文中。
一个行级盒子既表如今它是行级的,又表如今它的内容存在于包含他的行内格式化上下文中。设置了"display:inline"的不可替代元素将会产生一个行盒子。不是行盒子的行级盒子(如可替代的行级元素、行内块元素和行内表格元素)被称为原子行级元素,由于这些盒子在他们的行内格式化上下文中表现为一个单一的不透明盒子。
2.3 "display"属性
"display"属性的取值范围是: inline | 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
"display"属性的初始值为"inline"。
一下是每种取值的具体含义:
- block 应用该属性值的元素将会产生一个块盒子。
- inline-block 应用该属性值的元素将产生一个行级块容器。inline-block的内部被格式化成一个块盒子,元素自己被格式化成一个原子行级盒子。
- inline 应用该属性值的元素将会产生一到多个行盒子。
- list-item 应用该属性值的元素(好比html中的li)将会产生一个主块级盒子和一个标签盒子。
- none 应用该属性值的元素将不会出如今格式化结构(formatting structure)中,也就是说,元素不产生任何盒子,对布局没有任何影响。元素的后代元素也不产生盒子,元素和元素的内容被从格式化结构中彻底删除。经过设置后代元素的"display"属性值也不能改变。请注意,"display"为"none"时不产生任何不可见的盒子,实际上,根本不产生任何盒子。若是想 产生既不可见又影响格式化结构的盒子,请参考visibility属性。
- table,inline-table,table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, and table-caption;应用以上属性值的元素将表现得像一个表格元素。
注意,尽管"display"属性的初始值为"inline",可是UA的默认样式表可能覆盖这个值。
如下是一些display属性的例子:
p { display: block } em { display: inline } li { display: list-item } img { display: none }
3. 定位策略(Positioning schemes)
在css 2.1中,一个盒子将通过定位策略来进行定位:
- 正常文档流(Normal flow)。 在CSS2.1中,正常文档流包括块级盒子的块格式化上下文,行级盒子的行格式化上下文以及块级盒子和行级盒子的相对定位。
- 浮动(Floats)。 在浮动模型中,一个盒子先根据正常文档流定位,而后被从文档流中拿出来尽量的放到左/右边。上下文中的其余内容将流动到浮动元素的某一边。
- 绝对定位(Absolute positioning)。 在绝对定位模型中,盒子被从正常文档流中彻底移除(被移除的盒子对它原来的兄弟盒子将再也不产生任何影响) 而且根据它的包含块进行定位。
若是一个元素是浮动的、绝对定位的或者是根元素(root element),那么就称这个元素脱离了文档流(out-of-flow)。若是一个元素没有脱离文档流,那么就称这个元素在文档流内(in-flow)。一个脱离文档流的元素A,它的文档流包括元素A自己以及全部A的在文档流内的后代元素。
3.1 position 属性
position属性的取值范围是:static | relative | absolute | fixed | inherit, 初始值为static。每一个取值的含义以下:
- static 应用该属性值的盒子就是正常的盒子,根据正常的文档流来进行定位。top、right、bottom和left属性不生效。
- relative 应用该属性值的盒子,其位置将根据盒子在正常文档流中初始的位置以及一个偏移量来计算。即盒子的最终位置将相对于原来的位置发生必定的偏移。当盒子B采用相对定位后,盒子B后面的其余盒子的定位将不受影响,就好像盒子B没有采用相对定位同样。
- absolute 应用该属性值的盒子,其位置由top、right、bottom和left属性来决定,这些属性将根据盒子的包含块来肯定偏移量。采用绝对定位的盒子彻底脱离正常文档流,也就是说,绝对定位的盒子对其余盒子将再也不产生任何影响。采用绝对定位的盒子的外边距(margin)不与其余盒子的外边距重叠(collapse)。
- fixed 应用该属性值的盒子,其位置将根据绝对定位来计算,另外,盒子还将相对于必定的参照物固定不动。例如在视觉媒体中,采用fixed定位的盒子将相对于视口(viewport)固定不动。
UA可能默认根元素的定位为static定位。
3.2 盒子的偏移: top、right、bottom、left
若是一个元素的position属性值不为static,那么就称这个元素被定位了。被定位的元素将产生被定位的盒子,而后根据以下四个属性进行放置:
top
top属性的取值范围是: 绝对长度值 | 百分比 | auto | inherit, 初始值为auto。
该属性指定一个绝对定位的盒子的外边距上边界(top margin edge)距离这个盒子的包含块的上边界(top edge)的偏移量(距离)。对于采用相对定位的盒子来讲,这个偏移量根据盒子自己的上边界计算得出,也就是说,盒子初始采用正常文档流中的位置,而后在那个位置的基础上根据该属性值进行必定的偏移。
right
right属性的取值范围是: 绝对长度值 | 百分比 | auto | inherit ,初始值为auto。
跟top属性同样,该属性指定一个绝对定位的盒子的外边距右边界(right margin edge)距离这个盒子的包含块的右边界(right edge)的偏移量(距离)。对于采用相对定位的盒子来讲,这个偏移量根据盒子自己的右边界计算得出。
bottom
botton属性的取值范围是: 绝对长度值 | 百分比 | auto | inherit, 初始值为auto。
跟top属性同样,该属性指定一个绝对定位的盒子的外边距下边界(bottom margin edge)距离这个盒子的包含块的下边界(bottom edge)的偏移量(距离)。对于采用相对定位的盒子来讲,这个偏移量根据盒子自己的下边界计算得出。
left
left属性的取值范围是: 绝度长度值 | 百分比 | auto | inherit, 初始值为auto。
跟top属性同样,该属性指定一个绝对定位的盒子的外边距左边界(left margin edge)距离这个盒子的包含块的左边界(left edge)的偏移量(距离)。对于采用相对定位的盒子来讲,这个偏移量根据盒子自己的左边界计算得出。
上面这四个属性的具体取值有以下含义:
- 绝对长度值 相对于参考边的偏移量是个固定的距离且能够为负。
- 百分比 偏移量是盒子包含块宽度(left、right)或高度(top、bottom)的百分比,能够为负。
- auto 自动。
4. 正常文档流(Normal flow)
在正常文档流中的盒子都属于一个格式化上下文(formatting context)。这个格式化上下文既能够是块级的,也能够是行级的,但不能二者都是。块级盒子在块格式化上下文(block formatting context)中,行级盒子在行格式化上下文(inline formatting context)中。
4.1 块格式化上下文
浮动的元素、采用绝对定位的元素、不是块盒子的块容器(好比inline-block,table-cell和table-caption)以及设置了overflow且值不为visible(设置了visible的viewport除外)的块盒子将会为他们的内容创建新的块格式化上下文。
在块格式化上下文中,各个盒子从他们的包含块的顶部开始,竖直的顺次放置。相邻的两个盒子的竖直距离有margin属性决定。在同一个格式化上下文中的两个相邻的块级盒子的竖直外边距将会合并。
在块格式化上下文中,每一个盒子的左外边界与盒子的包含块的左边界相接(对于从右到左的状况,右外边界与右边界相接)。 即便当有浮动元素存在是也依然使用,除非这个盒子产生了新的块格式化上下文(这样的话,因为浮动,盒子的宽度将变小)。
5.浮动
浮动的盒子会被移动到当前行的左边或者右边。浮动最有趣的特色就是其余内容会在浮动的元素的旁边依次放置(或者经过设置clear属性禁止),或者说其余盒子会流动到浮动盒子的旁边。也就是说,其余盒子将沿着向左浮动的盒子的右边、向右浮动的盒子的左边依次放置。
一个浮动的盒子将会一直向左或向右移动,一直到触碰到包含块的边界或者其余浮动盒子的外边界。若是是行盒子的话,那么浮动盒子的外边界的顶部将与当前行盒子的顶部对其。
若是没有足够的水平空间,那么浮动的盒子将移至下一行直到有足够的空间或者行内已经没有其余浮动元素为止。
由于浮动盒子不在文档流中,因此在浮动盒子先后的未定位的块盒子将像浮动盒子不存在同样的竖直依次放置。可是,浮动盒子所在的当前行以及后面相邻的行盒子都会根据浮动盒子缩短宽度来给浮动盒子留下空间。
若是有个竖直的位置知足以下四个条件: (a)在行盒子的顶部或者顶部之下(b)在行盒子的底部或底部之上(c)在浮动盒子的外边界的顶部或者顶部之下(d)在浮动盒子的外边界的底部或者底部之上,那么行盒子将会换行。也就是说,若是浮动的盒子的外边界高度为0或者为负,那么行盒子不会缩短。
若是缩短的行盒子过短而不能包含任何内容,那么这个行盒子将会换行(而且高度会从新计算)直到有足够的空间或者没有浮动盒子为止。当前行内的任何在浮动盒子以前的盒子都将从新流动到浮动盒子的另外一边。换句话说,若是一个行内盒子放在了一个向左浮动盒子的前面,那么,向左浮动的盒子将会放在这一行的开始,与行盒子的顶部对其,以前的行内盒子将会移动到浮动盒子的右边。对于rtl和向右浮动的盒子同理。
table、块级可替换元素或者正常文档流中创建新的块格式化上下文的元素的border盒不能与任何在同一个格式化上下文中的浮动盒子的margin盒重叠。
5.1 float属性
float属性的取值范围是: left | right | none | inherit,初始值为none。
该属性值决定元素向左移动仍是向右移,或者根本不动。float属性能够被应用于任何元素上,除了绝对定位的元素。float属性的取值有以下含义:
- left 元素产生一个向左浮动的块盒子。其余内容流向盒子的右边。
- right 与left类似,盒子浮动到右边,其余内容流向盒子的左边。
- none 不浮动
以下9条规定了浮动元素的确切行为:
- 向左浮动的盒子的外左边界不能超过包含块的左边界。同理应用于向右浮动的盒子。
- 对于一个向左浮动的盒子,若是在这个盒子以前还有其余向左浮动的盒子,那么,这个盒子的左外边界不能超过其余任何向左浮动的盒子的右外边界,或者这个盒子的上边界必须比其余盒子的下边界低。同理应用于向右浮动的盒子。
- 任何向左浮动的盒子的右外边界不能超过任何与之相邻的向右浮动的盒子的左外边界。同理应用于向右浮动的盒子。
- 浮动盒子的上外边界不能比包含块的上边界高。当浮动发生在两个合并的margin中时,浮动的盒子根据一个假设的父的空匿名块盒子定位。
- 浮动盒子的上外边界不能比任何其余以前的块盒子或浮动盒子的上外边界高。
- 浮动盒子的上外边界不能比任何以前的行盒子的上边界高。
- 一个向左浮动的盒子,若是在他以前还有向左浮动的盒子,那么这个盒子的右外边界不能超过包含块的有边界,除非这个盒子已经尽量的向左了。同理应用于向右浮动的盒子。
- 浮动元素要尽量的往高放置。
- 向左浮动的盒子要尽量向左,向右浮动的盒子要尽量向右。可是相对于尽量向左或向右,更高的位置有更高的优先级。
下面的html片断,b浮动到右边:
<P>a<SPAN style="float: right">b</SPAN></P>
若是P元素的宽度足够,那么a和b将各占一边,以下:
5.2 clear属性
clear属性的取值范围是: none | left | right | both | inherit, 初始值为none。只应用于块级元素。
该属性决定元素盒子的哪一边不与浮动盒子相邻。clear属性不考虑被应用元素内部的浮动以及其余块格式化上下文中的浮动。
属性取值含义以下:
- left 应用该属性值的元素盒子的上边界要低于该元素以前的左浮动元素盒子的底外边界。
- right 应用该属性值的元素盒子的上边界要低于该元素以前的右浮动元素盒子的底外边界。
- both 应用该属性值的元素盒子的上边界要低于该元素以前的左浮动或右浮动元素盒子的底外边界。
- none 不浮动。
全部不是none的值都将引入空隙(clearance)。clearance禁止margin合并,表现得就像元素的上外边距外还有一段空间。
要计算应用了clear属性的元素的clearance,首先须要找到元素上边界的假定位置。这个假定位置就是当clear属性值为none时元素实际上的上边界。
若是假定的元素的上边界不能越过相关的浮动元素(past the relevant floats),那么就须要引入clearance。
空隙的大小为以下两个值中的较大值:
- 将元素的上边界与最低的浮动元素的底外边界对齐须要的空间大小。
- 将元素的上边界放置到它假定的位置须要的空间大小。
注意,空隙的大小可能为负也可能为0.
6.display、position和float的关系
这三个属性都影响盒子的产生以及定位,他们关系以下:
- 若是display的值为none,那么position和float不起做用。在这种状况下,元素不产生盒子。
- 不然,若是position的值为absolute或者fixed,那么盒子就使用绝对定位,float的最终使用的值为none,display的取值依据以下表格来定。盒子的显示位置根据top、right、bottom和left属性决定。
- 不然,若是float的取值不会none,那么盒子将会浮动,display的取值参照下表。
- 不然,若是元素是根元素,那么display的取值参照下表。
- 不然,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 |
blockcss |
其余 |
与指定的值相同html |