内容
元素(生成的)盒的位置和大小有时是根据一个特定矩形计算的,叫做该元素的包含块(containing block)。元素包含块的定义如下:
如果没有这样的祖先,包含块就是初始包含块
分页媒体中,一个绝对定位的元素是相对于其包含块定位的,忽略所有页结束符(就像文档是连续的一样),该元素随后可能被拆分到多页
对于绝对定位的内容,如果被解析到一个除元素所在的页面(当前页面)之外的其它页面上的位置,或者是当前页上已经为打印渲染好了的位置,打印机可能把该内容放在
注意,被跨页分割的块级元素可能在每一页具有不同的宽度,还可能存在特定设备限制
不做任何定位的话,如下文档
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <HTML> <HEAD> <TITLE>Illustration of containing blocks</TITLE> </HEAD> <BODY id="body"> <DIV id="div1"> <P id="p1">This is text in the first paragraph...</P> <P id="p2">This is text <EM id="em1"> in the <STRONG id="strong1">second</STRONG> paragraph.</EM></P> </DIV> </BODY> </HTML>
建立的包含块(C.B.)如下:
For box generated by | C.B. is established by |
---|---|
html | initial C.B. (UA-dependent) |
body | html |
div1 | body |
p1 | div1 |
p2 | div1 |
em1 | p2 |
strong1 | p2 |
如果我们对"div1"定位:
#div1 { position: absolute; left: 50px; top: 50px }
它的包含块就不再是"body"了,变成了初始包含块(因为没有其它定位祖先盒了)
如果我们也对"em1"定位:
#div1 { position: absolute; left: 50px; top: 50px } #em1 { position: absolute; left: 100px; top: 100px }
包含块表变成了:
For box generated by | C.B. is established by |
---|---|
html | initial C.B. (UA-dependent) |
body | html |
div1 | initial C.B. |
p1 | div1 |
p2 | div1 |
em1 | div1 |
strong1 | em1 |
对"em1"定位后,它的包含块变成了最近的定位的祖先盒(即,由"div1"生成的)
Value: | <length> | <percentage> | auto | inherit |
Initial: | auto |
Applies to: | 除非替换的行内元素,表格行和行组(row group) 外的所有元素 |
Inherited: | no |
Percentages: | 参照包含块的宽度 |
Media: | visual |
Computed value: | 与指定值相同的百分比或者'auto',或者绝对长度 |
该属性指定了盒的内容宽度(content width)
该属性不适用于非替换的行内元素。非替换的行内元素盒的内容宽度是它里面渲染的内容(的内容宽度)(在在子级的任何相对偏移之前)。回想一下,行内盒都排列在行框里面。行框的宽度由它们的包含块决定,但可能因为浮动的出现而被缩短
属性值含义如下:
负值对于'width'是非法的
例如,如下规则设置了段落的内容宽度为固定的100像素:
p { width: 100px }
元素的'width','margin-left','margin-right','left'和'right'属性用于布局的值,取决于生成盒的类型以及相互影响(用于布局的值有时被称为应用值)。原则上,应用值与计算值一样,都是把'auto'替换成一些合适的值,百分比相对其包含块来计算,但也存在例外。以下情况需要加以区分:
对于1-6和9-10条,相对定位的元素的'left'和'right'的值由9.4.3节中的规则确定
注意 下面计算的'width'应用值是个初步值,可能不得不经多次计算,取决于'min-width'和'max-width',见下面的最小、最大宽度章节
'width'属性不适用。计算值为'auto'的'margin-left'或者'margin-right'对应的应用值为'0'
计算值为'auto'的'margin-left'或者'margin-right'对应的应用值为'0'
如果'height'和'width'计算值都是'auto',并且该元素还具有固有宽度,那么这个固有宽度就是'width'的应用值
如果'height'和'width'的计算值都是'auto',并且该元素没有固有宽度,但具有固有高度和固有比例;或者如果'width'的计算值为'auto','height'具有其它计算值,并且该元素有固有比例;那么'width'的应用值为:
(高度的应用值) * (固有比例)
如果'height'和'width'的计算值都是'auto',并且该元素具有固有比例但没有固有高度或者宽度,那么'width'的应用值在CSS 2.1是未定义的。然而,建议如果包含块的宽度不依赖替换元素的宽度,那么'width'的应用值根据用于常规流中块级非替换元素的约束方程(constraint equation)来计算
否则,如果'width'的计算值为'auto',并且该元素具有固有宽度,那么这个固有宽度就是'width'的应用值
否则,如果'width'的计算值为'auto',但不满足上面的条件,那么'width'的应用值变为300px。如果300px对于适应设备来说太宽了,UA应该应用适应设备的最大的比例为2:1的矩形代替
其它属性的应用值,必须保证如下约束:
'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = 包含块的宽度
如果'width'不是'auto',并且'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width'(再加上所有不为'auto'的'margin-left'或者'margin-right')大于包含块的宽度,那么所有'margin-left'或者'margin-right'的'auto'值在下列规则中会被当作0
如果以上(属性)的计算值都不是'auto',就说该值被过度限制(over-constrained)了,其中一个应用值将与其计算值不同。如果包含块的'direction'属性值为'ltr','margin-right'的指定值会被忽略,并且重新计算该值,以便让等式成立。如果'direction'的值为'rtl',就换成'margin-left'
如果有且仅有一个值被指定为'auto',其应用值由等式得出
如果'width'被设置为'auto',所有其它的'auto'值都变为'0'并且'width'由产生的等式得出
如果'margin-left'和'margin-right'都是'auto',那么它们的应用值相等。这会让该元素相对于其包含块边界水平居中
'width'的应用值由行内替换元素决定。然后,用非替换的块级元素的规则来确定外边距
如果'margin-left'或者'margin-right'的计算值为'auto',则其应用值为'0'
如果'width'的计算值为'auto',应用值就是“自适应(shrink-to-fit)”宽度
自适应宽度的计算与用自动表格布局算法去算一个表格单元的宽度类似。粗略地讲:通过格式化不含除显式换行外的换行来计算首选宽度(preferred width),然后计算首选最小宽度(preferred minimum width),例如,通过尝试所有可能的换行。CSS 2.1没有定义准确的算法。第三步,算出可用宽度(available width):这种情况下,就是包含块的宽度减去'margin-left','border-left-width','padding-left','padding-right','border-right-width','margin-right'以及所有相关滚动条的宽度的应用值
那么自适应宽度就是:min(max(首选最小宽度, 可用宽度), 首选宽度)
如果'margin-left'或者'margin-right'的计算值为'auto',它们的应用值就是'0'。'width'的应用值由行内替换元素决定
就本节和下一节而言,术语(元素的)“静态位置(static position)”,大致指的是元素在常规流中的位置。更精确地:
但不用实际计算假想盒的尺寸,用户代理可以随意猜测它可能的位置
出于计算静态位置的目的,fixed定位元素的包含块为初始包含块,而不是视口,并且所有可滚动的盒应该假设滚动到其起点
决定这些元素的应用值的约束是:
'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = 包含块的宽度
如果'left','width'和'right'全都是'auto':先把所有的值为'auto'的'margin-left'和'margin-right'设置为0。然后,如果建立静态位置包含块的元素的'direction'属性为'ltr',把'left'设置为静态位置并应用下面的第3条规则;否则把'right'设置为静态位置并应用下面的第1条规则
如果这3个值都不是'auto':如果'margin-left'和'margin-right'都是'auto',解方程时要添上额外的约束:2个margin的值相等,除非这会让它们为负。这种情况下,如果包含块的direction是'ltr' ('rtl'),把'margin-left' ('margin-right')设置为0,再求出'margin-right' ('margin-left')。如果'margin-left'或者'margin-right'有一个是'auto',就解方程求这个值。如果该值被过度限制了,就忽略'left'(如果包含块的'direction'属性是'rtl')或者'right'(如果'direction'为'ltr')的值,再求出这个值
否则,把值为'auto'的'margin-left'和'margin-right'设置为0,再在下面6条规则中挑1条合适的应用
自适应宽度的计算与用自动表格布局算法去算一个表格单元的宽度类似。大致是这样:通过格式化不含除显式换行外的换行来计算首选宽度(preferred width),然后计算首选最小宽度(preferred minimum width),例如,通过尝试所有可能的换行。CSS 2.1没有定义准确的算法。第三步,算出可用宽度(available width):通过把'left'(第1种情况 译注:指的是上面1-6中需要计算自适应宽度的两种,分别是1和3)或者'right'(第3种情况)设置为0后求'width'来确定
那么自适应宽度就是:min(max(首选最小宽度, 可用宽度), 首选宽度)
这种情况下,10.3.7节中直到包括约束方程的部分都适用,但10.3.7节剩余部分要用下面的规则替换掉:
如果'width'为'auto',应用值就与浮动元素一样是自适应宽度
计算值为'auto'的'margin-left'或者'margin-right'的应用值变为'0'
与行内替换元素完全一致
Value: | <length> | <percentage> | inherit |
Initial: | 0 |
Applies to: | 除非替换的行内元素,表格行和行组(row group)外的所有元素 |
Inherited: | no |
Percentages: | 参照包含块的宽度 |
Media: | visual |
Computed value: | 与指定值相同的百分比或者绝对长度 |
Value: | <length> | <percentage> | none | inherit |
Initial: | none |
Applies to: | 除非替换的行内元素,表格行和行组(row group)外的所有元素 |
Inherited: | no |
Percentages: | 参照包含块的宽度 |
Media: | visual |
Computed value: | 与指定值相同的百分比或者绝对长度或者'none' |
这两个属性允许编写者把内容宽度约束到一个特定范围。值含义如下:
负值对'min-width'和'max-width'是非法的
CSS 2.1中,'min-width'和'max-width'对表格,行内表格,表格单元,表格列和列组(column group)的效果是未定义的
下面的算法描述了这两个属性怎样影响'width'属性的应用值:
这些步骤不影响上述属性真实的计算值
然而,对于具有固有比例并且'width'和'height'都被指定为'auto'的的替换元素,算法如下:
从表中选择相应的约束冲突的解析高度和宽度值。取max-width和max-height作为max(min, max),以保证min≤max成立。表中的w和h代表忽略'min-width','min-height','max-width'和'max-height'属性后,width和height计算的结果。一般它们都是固有宽度和高度,但它们可能不属于具有固有比例的替换元素的情况
注意:如果设置了显式宽高,而其它尺寸为auto,对auto边应用一个最小或最大约束会造成过度约束的情况。规范对这种行为很明确,但可能不是编写者所预期的。CSS3的object-fit属性可以用来得到这种情况下不同的结果
违反的约束 | 解析宽度 | 解析高度 |
---|---|---|
none | w | h |
w > max-width | max-width | max(max-width * h/w, min-height) |
w < min-width | min-width | min(min-width * h/w, max-height) |
h > max-height | max(max-height * w/h, min-width) | max-height |
h < min-height | min(min-height * w/h, max-width) | min-height |
(w > max-width) and (h > max-height), where (max-width/w ≤ max-height/h) | max-width | max(min-height, max-width * h/w) |
(w > max-width) and (h > max-height), where (max-width/w > max-height/h) | max(min-width, max-height * w/h) | max-height |
(w < min-width) and (h < min-height), where (min-width/w ≤ min-height/h) | min(max-width, min-height * w/h) | min-height |
(w < min-width) and (h < min-height), where (min-width/w > min-height/h) | min-width | min(max-height, min-width * h/w) |
(w < min-width) and (h > max-height) | min-width | max-height |
(w > max-width) and (h < min-height) | max-width | min-height |
然后应用上面的“计算width与margin”的规则,就当'width'的计算值是该值
Value: | <length> | <percentage> | auto | inherit |
Initial: | auto |
Applies to: | 除非替换的行内元素,表格列和列组(column group)外的所有元素 |
Inherited: | no |
Percentages: | 见下文 |
Media: | visual |
Computed value: | 百分比或者'auto'(见下文的<percentage>)或者绝对长度 |
该属性指定了盒的内容高度(content height)
该属性不适用于非替换的行内元素,替代规则见计算非替换的行内元素的height和margin小节
值含义如下:
注意,绝对定位元素的包含块的高度独立于该元素本身的大小,因此这种元素上的百分比高度都可以计算出来(can always be resolved)。然而,可能直到文档中在此之后的元素处理完毕后,才能获知该高度
负值对于'height'是非法的
对于计算'top','margin-top','height','margin-bottom'和'bottom'的值,必须区分盒的种类:
对于1-6和9-10条,'top'和'bottom'的应用值由9.4.3节的规则确定
注意:这些规则同样适用于根元素,像其它元素一样
注意 下面计算的'height'的应用值是一个初步值,可能不得不经多次计算,取决于'min-height'和'max-height',见下面的最小、最大高度章节
'height'属性不适用。内容区(content area)的高度应该基于字体,但本规范没有具体说明。例如,UA可以使用em框(em-box)或者字体的最大上伸部(ascender)和下延部(descender)(后者能够确保em框上方或者下方的字形(glyph)仍处于内容区里,但会导致不同字体有不同大小的盒;前者能够确保编写者可以相对于'line-height'控制背景样式化,但会导致字形绘制在其内容区外)
注意:CSS 3可能会包含用来选择用于内容高度的字体测量方法的属性
行内非替换盒的垂直内边距,边框和外边距从内容区的顶部和底部开始,并且与'line-height'无关。'line-height'只在计算行框的高度时使用
如果应用了多个字体(发现字形是多种字体时会发生这种情况),内容区的高度不由本规范定义。然而,我们建议高度让内容区刚好放得下元素中的所有字体的(1)em盒或者(2)最大上伸部和下延部。注意,这可能大于所有涉及的字体(的高度),取决于字体的基线对齐方式
如果'margin-top'或者'margin-bottom'为'auto',其应用值为0
如果'height'和'width'的计算值都是'auto',并且元素还具有固有高度,那么这个固有高度就是'height'的应用值
否则,如果'height'的计算值为'auto',并且该元素具有固有比例,那么'height'的应用值为:
(宽度的应用值) / (固有比例)
否则,如果'height'的计算值为'auto',并且该元素具有固有高度,那么这个固有高度就是'height'的应用值
否则,如果'height'的计算值为'auto',但上面的条件都不满足,那么'height'的应用值必须设置为比例为2:1,高度不超过150px并且宽度不超过设备宽度的最大矩形的高度
本节也适用于常规流中的块级不可替换元素,当'overflow'的计算值不为'visible'但已经传播到视口时
如果'margin-top'或'margin-bottom'为'auto',则其应用值为0。如果'height'为'auto',高度取决于该元素是否含有块级子级以及是否具有padding或border:
该元素的高度为从其内容上边界到下面第一个适用的(位置)的距离:
只考虑常规流中的子级(即,浮动盒和绝对定位的盒会被忽略,并且相对定位的盒不考虑其偏移)。注意子级盒可以是一个匿名块盒
就本节和下一节而言,术语(一个元素的)"static position",大致指的是元素在常规流中的位置。更精确地,'top'的静态位置是从包含块的上边界到假想盒的上外边距边界的距离,假想盒是该元素的第一个指定了'position'值为'static','float'为'none'并且'clear'为'none'的盒(注意,由于9.7节中的规则,可能还需要为'display'假定一个不同的计算值)。如果假想盒在包含块上方,该值为负
但不用实际计算这个假想盒的尺寸,用户代理可以自由猜测它可能的位置
就计算静态位置而言,fixed定位元素的包含块是初始包含块而不是视口
对于绝对定位的元素,垂直方向(dimension)的应用值必须满足这样的约束:
'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = 包含块的高度
如果'top','height'和'bottom'都是auto,把'top'设置为静态位置并应用下面的第3条规则:
如果这3个值都不是'auto':如果'margin-top'和'margin-bottom'都是'auto',解方程时要添上额外的约束:2个margin的值相等。如果'margin-top'或者'margin-bottom'有一个是'auto',解方程求出这个值。如果该值被过度约束了,就忽略'bottom'的值再求这个值
否则,在下面6条规则中挑1条合适的应用
这种情况与前一种类似,只是(expect that)元素具有固有高度。步骤(sequence)替换为:
本节适用于:
如果'margin-top'或者'margin-bottom'为'auto',其应用值为0。如果'height'是'auto',高度取决于该元素的后代,根据10.6.7
对于'inline-block'元素,在计算行框的高度时,使用外边距框(margin box)
特定情况下(例如,见上面的10.6.4节和10.6.6节),一个建立了块格式化上下文的元素的高度按照如下规则计算:
如果它只含有行内级子级,高度就是最高的行框的顶端与最低的行框的底端之间的距离
如果它只含有块级子级,高度就是最高的块级子级盒的上外边距边界到最低的块级子级盒的下外边距边界之间的距离
绝对定位的子级会被忽略,并且相对定位的盒不考虑其偏移。注意,子级盒可以是一个匿名块盒
此外,如果该元素含有任意下外边距边界位于元素的内容下边界下方的的浮动后代,那么高度增加至能够包含这些边界。只考虑参与此块级格式化上下文的浮动,例如,不考虑绝对定位的后代中的浮动或其它浮动
有时把元素的高度约束到一个特定范围很有用。两个属性提供了这种功能:
Value: | <length> | <percentage> | inherit |
Initial: | 0 |
Applies to: | 除非替换的行内元素,表格列和列组(column group)外的所有元素 |
Inherited: | no |
Percentages: | 见下文 |
Media: | visual |
Computed value: | 与指定值相同的百分比,或者绝对长度 |
Value: | <length> | <percentage> | none | inherit |
Initial: | none |
Applies to: | 除非替换的行内元素,表格列和列组(column group)外的所有元素 |
Inherited: | no |
Percentages: | 见下文 |
Media: | visual |
Computed value: | 与指定值相同的百分比或者绝对长度或者'none' |
这两个属性允许编写者把盒的高度约束到一个特定范围。值含义如下:
负值对'min-height'和'max-height'是非法的
CSS 2.1中,'min-height'和'max-height'对表格,行内表格,表格单元,表格行和行组(row group)的效果是未定义的
如下算法描述了这两个属性怎样影响'height'属性的应用值:
这些步骤不会影响以上属性真实的计算值,'height'应用值的变更不会影响外边距合并,除了在“合并外边距(8.3.1)”中特别提到的关于'min-height'或者'max-height'的规则
然而,对于'width'和'height'的计算值为'auto'的替换元素,就用上面的最小、最大宽度中的算法来算出宽度和高度的应用值。然后把产生的宽度和高度作为计算值再应用上面的“计算height与margin”中的规则
如行内格式化上下文节所述,用户代理把行内级盒排列在一个行框的垂直堆叠里。行框的高度由下列规则决定:
空行内元素生成空的行内盒,但这些盒仍然具有margin,padding,border和line height,从而影响这些计算,就像有内容的元素一样
CSS假定任何字体都具有指定了基线上方的高度(height)和下方的深度(depth)特征的字体规格(font metrics)。本节中,我们用A表示高度(对于一个给定大小的指定字体),D表示深度。我们还定义了AD = A + D,表示从顶端到底端的距离(见下面对如何找出TrueType和OpenType字体的A和D的注释)。注意,这些都是字体整体的规格,并没有与所有单个字形的上伸部(ascender)和下延部(descender)对应
用户代理必须把一个非替换的行内盒中的字形彼此之间按其相关基线对齐,然后,对每个字形,确定A和D。注意单一元素中的字形可能来自不同的字体,并且因此不一定具有相同的A和D。如果行内盒不含任何字形,就认为它含有一个strut(一个不可见的0宽字形),它具有该元素的第一个可用字体的A和D
然后对每个字形,确定要添加的行距(leading)L,其中L = 'line-height' - AD。半行距添在A上方,而另一半添在D下方,字形及其行距在基线上方的总高度为A' = A + L/2,总深度为D' = D + L/2
注意 L可以为负
行内盒的高度包含所有字形及其两边的半行距,所以恰好是'line-height'。子级元素的盒不会影响这个高度
尽管非替换元素的外边距,边框和内边距不会算入行框的计算,它们仍然渲染在行内盒周围。这意味着如果用'line-height'指定的高度小于包含的盒(contained boxes)的内容高度,背景与内边距和外边距的颜色可能会“流(bleed)”进相邻的行框。用户代理应该按文档顺序渲染这些盒。这将导致后续行的边框绘制在之前行的边框和文本上面(覆盖)
注意 CSS 2.1没有定义一个行内盒的内容区(content area)是什么(见上面的10.6.1),并且因此不同的UA可能在不同的地方绘制背景和边框
注意 建议使用OpenType或者TrueType字体的实现根据字体的OS/2表中的"sTypoAscender"和"sTypoDescender"规格(metrics)找出相应的A和D(在缩放当前元素的字体大小后)。如果没有这些规格,就应该用HHEA表中的"Ascent"和"Descent"规格
Value: | normal | <number> | <length> | <percentage> | inherit |
Initial: | normal |
Applies to: | 所有元素 |
Inherited: | yes |
Percentages: | 参考元素自身的字体大小 |
Media: | visual |
Computed value: | 对于<length>和<percentage>是绝对的值,否则与指定值相同 |
对于一个内容由行内级元素组成的块容器元素,'line-height'指定了元素内行框的最小高度。这个最小高度包含基线上方的最小高度和下方的最小深度,就像每个行框以一个具有该元素的字体和行高属性的0宽行内盒开始。我们把这种假想盒叫做"strut"(这个名字是受TeX的启发)
假设字体基线上方和下方的高度和深度存在于该字体所包含的规格中(更多详细信息,见CSS level 3)
对于非替换的行内元素,'line-height'指定的高度用来计算行框高度
属性值含义如下:
下例的这3条规则会产生相同的行高:
div { line-height: 1.2; font-size: 10pt } /* number */ div { line-height: 1.2em; font-size: 10pt } /* length */ div { line-height: 120%; font-size: 10pt } /* percentage */
当一个元素含有以多种字体渲染的文本时,用户代理可以根据最大字体大小来确定“常规”'line-height'值
注意 当一个块容器盒里的所有行内盒只有一个'line-height'值并且它们都是相同的字体时(并且不存在替换元素,行内元素等等),以上内容将确保连续行的基线都恰好相隔'line-height'。在不得不对齐字体不同的文本列时,这一点很重要,例如在表格中
Value: | baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage> | <length> | inherit |
Initial: | baseline |
Applies to: | 行内级和'table-cell'元素 |
Inherited: | no |
Percentages: | 参照元素自身的'line-height' |
Media: | visual |
Computed value: | 对于<percentage>和<length>,就是绝对长度,否则与指定值相同 |
该属性会影响由一个行内级元素生成的盒的行框内部的垂直定位
注意 该属性的值在表格上下文中具有不同的含义。详细信息请查看表格高度算法章节
下列值只对父级行内元素或者一个父级块容器元素的strut有效
在下面的定义中,对于行内非替换元素,用于对齐的盒是那个高度为'line-height'(包括该盒的字形和两边的半行距,见上文)的盒。对于其它所有元素,用于对齐的盒都是外边距框(margin box)
下面的值让元素相对于一个行框对齐。因为该元素可能具有相对于它对齐的子级(相应的,(这些子级也)可能具有相对于它们对齐的后代),这些值使用对齐子树的边界(the bounds of the aligned subtree)。行内元素的对齐子树包括这个元素和所有'vertical-align'的计算值不为'top'或者'bottom'的子级行内元素的对齐子树。对齐子树的顶端是子树中盒的顶端最高的(位置),底端(的定义)与之类似
'inline-table'(盒)的基线是表格第一行的基线
'inline-block'(盒)的基线是它的最后一个常规流中的行框的基线,除非它没有流内行框或者其'overflow'属性的计算值不为'visible',此时基线是下外边距边界