10 视觉格式化模型细节

内容

10.1 “包含块”的定义

元素(生成的)盒的位置和大小有时是根据一个特定矩形计算的,叫做该元素的包含块(containing block)。元素包含块的定义如下:

  1. 根元素所在的包含块是一个被称为初始包含块的矩形。对于连续媒体,尺寸取自视口的尺寸,并且被固定在画布开始的位置;对于分页媒体就是页区(page area)。初始包含块的'direction'属性与根元素的相同
  2. 对于其它元素,如果该元素的position是'relative'或者'static',包含块由其最近的块容器祖先盒的内容边界形成
  3. 如果元素具有'position: fixed',包含块由连续媒体的视口或者分页媒体的页区建立
  4. 如果元素具有'position: absolute',包含块由最近的'position'为'absolute','relative'或者'fixed'的祖先建立,按照如下方式:
    1. 如果该祖先是一个行内元素,包含块就是环绕着为该元素生成的第一个和最后一个行内盒的内边距框的边界框(bounding box)。在CSS 2.1中,如果该行内元素被跨行分割了,那么包含块是未定义的
    2. 否则,包含块由该祖先的内边距边界形成

    如果没有这样的祖先,包含块就是初始包含块

分页媒体中,一个绝对定位的元素是相对于其包含块定位的,忽略所有页结束符(就像文档是连续的一样),该元素随后可能被拆分到多页

对于绝对定位的内容,如果被解析到一个除元素所在的页面(当前页面)之外的其它页面上的位置,或者是当前页上已经为打印渲染好了的位置,打印机可能把该内容放在

注意,被跨页分割的块级元素可能在每一页具有不同的宽度,还可能存在特定设备限制

示例:

不做任何定位的话,如下文档

<!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
htmlinitial C.B. (UA-dependent)
bodyhtml
div1body
p1div1
p2div1
em1p2
strong1p2

如果我们对"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
htmlinitial C.B. (UA-dependent)
bodyhtml
div1initial C.B.
p1div1
p2div1
em1div1
strong1em1

对"em1"定位后,它的包含块变成了最近的定位的祖先盒(即,由"div1"生成的)

10.2 内容宽度'width'属性

'width'
Value:  <length> | <percentage> | auto | inherit
Initial:  auto
Applies to:  除非替换的行内元素,表格行和行组(row group) 外的所有元素
Inherited:  no
Percentages:  参照包含块的宽度
Media:  visual
Computed value:  与指定值相同的百分比或者'auto',或者绝对长度

该属性指定了盒的内容宽度(content width)

该属性不适用于非替换的行内元素。非替换的行内元素盒的内容宽度是它里面渲染的内容(的内容宽度)(在在子级的任何相对偏移之前)。回想一下,行内盒都排列在行框里面。行框的宽度由它们的包含块决定,但可能因为浮动的出现而被缩短

属性值含义如下:

<length>
用一个长度单位指定内容区(content area)的宽度
<percentage>
指定一个百分比宽度。该百分比根据生成的盒的包含块的宽度来计算。如果包含块的宽度取决于该元素的宽度,那么产生的布局在CSS 2.1中是未定义的注意:对于那些包含块是基于一个块容器元素的绝对定位元素,百分比是根据这个元素的内边距框的宽度计算的。这与CSS1不同,(CSS1中)百分比宽度总是根据父级元素的内容框计算的
auto
宽度取决于其它属性的值,见下面的章节

负值对于'width'是非法的

示例:

例如,如下规则设置了段落的内容宽度为固定的100像素:

p { width: 100px }

10.3 计算width与margin

元素的'width''margin-left''margin-right''left''right'属性用于布局的值,取决于生成盒的类型以及相互影响(用于布局的值有时被称为应用值)。原则上,应用值与计算值一样,都是把'auto'替换成一些合适的值,百分比相对其包含块来计算,但也存在例外。以下情况需要加以区分:

  1. 行内非替换元素
  2. 行内替换元素
  3. 常规流中的块级非替换元素
  4. 常规流中的块级替换元素
  5. 浮动的非替换元素
  6. 浮动的替换元素
  7. 绝对定位的非替换元素
  8. 绝对定位的替换元素
  9. 常规流中非替换的'inline-block'元素
  10. 常规流中替换的'inline-block'元素

对于1-6和9-10条,相对定位的元素的'left'和'right'的值由9.4.3节中的规则确定

注意 下面计算的'width'应用值是个初步值,可能不得不经多次计算,取决于'min-width''max-width',见下面的最小、最大宽度章节

10.3.1 行内非替换(non-replaced)元素

'width'属性不适用。计算值为'auto'的'margin-left'或者'margin-right'对应的应用值为'0'

10.3.2 行内替换元素

计算值为'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的矩形代替

10.3.3 常规流中的块级非替换元素

其它属性的应用值,必须保证如下约束

'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',那么它们的应用值相等。这会让该元素相对于其包含块边界水平居中

10.3.4 常规流中的块级替换元素

'width'的应用值由行内替换元素决定。然后,用非替换的块级元素的规则来确定外边距

10.3.5 浮动的非替换元素

如果'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(首选最小宽度, 可用宽度), 首选宽度)

10.3.6 浮动的替换元素

如果'margin-left'或者'margin-right'的计算值为'auto',它们的应用值就是'0'。'width'的应用值由行内替换元素决定

10.3.7 绝对定位的非替换元素

就本节和下一节而言,术语(元素的)“静态位置(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条合适的应用

  1. 如果'left'和'width'都是'auto','right'不是'auto',则宽度自适应,再求出'left'
  2. 如果'left'和'right'都是'auto','width'不是'auto',如果建立静态位置包含块的元素的'direction'属性是'ltr',就把'left'设置为静态位置,否则把'right'设置为静态位置。然后求出'left'(如果'direction'是'rtl')或者'right'(如果'direction'是'ltr')
  3. 如果'width'和'right'都是'auto','left'不是'auto',则宽度自适应,再求出'right'
  4. 如果'left'是'auto','width'和'right'都不是'auto',则求出'left'
  5. 如果'width'是'auto','left'和'right'都不是'auto',则求出'width'
  6. 如果'right'是'auto','left'和'width'都不是'auto',则求出'right'

自适应宽度的计算与用自动表格布局算法去算一个表格单元的宽度类似。大致是这样:通过格式化不含除显式换行外的换行来计算首选宽度(preferred width),然后计算首选最小宽度(preferred minimum width),例如,通过尝试所有可能的换行。CSS 2.1没有定义准确的算法。第三步,算出可用宽度(available width):通过把'left'(第1种情况 译注:指的是上面1-6中需要计算自适应宽度的两种,分别是1和3)或者'right'(第3种情况)设置为0后求'width'来确定

那么自适应宽度就是:min(max(首选最小宽度, 可用宽度), 首选宽度)

10.3.8 绝对定位的替换元素

这种情况下,10.3.7节中直到包括约束方程的部分都适用,但10.3.7节剩余部分要用下面的规则替换掉:

  1. 'width'的应用值由行内替换元素决定。如果'margin-left'或者'margin-right'被指定为'auto',其应用值由下面的规则决定:
  2. 如果'left''right'值都是'auto',然后如果建立静态位置包含块的元素的'direction'属性为'ltr',把'left'设置为静态位置,否则如果'direction'为'rtl',就把'right'设置为静态位置
  3. 如果'left'或者'right'为'auto',把所有值为'auto'的'margin-left'或者'margin-right'替换为'0'
  4. 如果此时'margin-left''margin-right'仍然都是'auto',解方程时要添上额外的约束:2个margin必须相等,除非这会让它们为负。这种情况下,如果包含块的direction是'ltr' ('rtl'),把'margin-left' ('margin-right')设置为0,再求出'margin-right' ('margin-left')
  5. 如果此时只剩一个'auto'了,就解方程求出这个值
  6. 如果此时该值被过度限制了,忽略'left'(包含块的'direction'属性为'rtl'时)或者'right''direction'为'ltr'时),再求出这个值

10.3.9 常规流中非替换的inline-block元素

如果'width'为'auto',应用值就与浮动元素一样是自适应宽度

计算值为'auto'的'margin-left'或者'margin-right'的应用值变为'0'

10.3.10 常规流中替换的inline-block元素

行内替换元素完全一致

10.4 最小、最大宽度'min-width''max-width'

'min-width'
Value:  <length> | <percentage> | inherit
Initial:  0
Applies to:  除非替换的行内元素,表格行和行组(row group)外的所有元素
Inherited:  no
Percentages:  参照包含块的宽度
Media:  visual
Computed value:  与指定值相同的百分比或者绝对长度
'max-width'
Value:  <length> | <percentage> | none | inherit
Initial:  none
Applies to:  除非替换的行内元素,表格行和行组(row group)外的所有元素
Inherited:  no
Percentages:  参照包含块的宽度
Media:  visual
Computed value:  与指定值相同的百分比或者绝对长度或者'none'

这两个属性允许编写者把内容宽度约束到一个特定范围。值含义如下:

<length>
指定一个固定的最小或者最大应用宽度
<percentage>
指定一个用来确定应用值的百分比。百分比参照生成盒的包含块的宽度来计算。如果包含块的宽度为负,那么应用值为0。如果包含块的宽度取决于该元素的宽度,那么产生的布局在CSS 2.1中是未定义的
none
(只对'max-width'有效)对盒的宽度没有限制

负值对'min-width''max-width'是非法的

CSS 2.1中,'min-width'和'max-width'对表格,行内表格,表格单元,表格列和列组(column group)的效果是未定义的

下面的算法描述了这两个属性怎样影响'width'属性的应用值

  1. 初步的应用宽度按照上面的“计算width与margin”来计算(不考虑'min-width''max-width'
  2. 如果初步的应用值大于'max-width',就再应用一遍上面的规则,但这次把'max-width'的计算值作为'width'的计算值
  3. 如果产生的宽度小于'min-width',就再应用一遍上面的规则,但这次把'min-width'值作为'width'的计算值

这些步骤不影响上述属性真实的计算值

然而,对于具有固有比例并且'width''height'都被指定为'auto'的的替换元素,算法如下:

从表中选择相应的约束冲突的解析高度和宽度值。取max-widthmax-height作为max(min, max),以保证minmax成立。表中的wh代表忽略'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'的计算值是该值

10.5 内容高度'height'属性

'height'
Value:  <length> | <percentage> | auto | inherit
Initial:  auto
Applies to:  除非替换的行内元素,表格列和列组(column group)外的所有元素
Inherited:  no
Percentages:  见下文
Media:  visual
Computed value:  百分比或者'auto'(见下文的<percentage>)或者绝对长度

该属性指定了盒的内容高度(content height)

该属性不适用于非替换的行内元素,替代规则见计算非替换的行内元素的height和margin小节

值含义如下:

<length>
用一个长度值指定内容区(content area)的高度
<percentage>
指定一个百分比高度。百分比参照生成盒的包含块的高度。如果包含块的高度没有显式指定(即取决于内容高度),并且该元素不是绝对定位的,则计算值为'auto'。根元素上的百分比高度是相对于初始包含块 注意:对于那些包含块基于一个块级元素的绝对定位元素,百分比根据这个元素的内边距框(padding box)的高度来计算。这与CSS1不同,(CSS1中)百分比总是根据父级元素的内容框(content box)来计算
auto
高度取决于其它属性的值,见下文

注意,绝对定位元素的包含块的高度独立于该元素本身的大小,因此这种元素上的百分比高度都可以计算出来(can always be resolved)。然而,可能直到文档中在此之后的元素处理完毕后,才能获知该高度

负值对于'height'是非法的

示例:

例如,如下规则把段落的内容高度设置为100像素:

p { height: 100px }

那些内容高度超过100像素的段落将根据'overflow'属性溢出

10.6 计算height与margin

对于计算'top''margin-top''height''margin-bottom''bottom'的值,必须区分盒的种类:

  1. 行内非替换元素
  2. 行内替换元素
  3. 常规流中的块级非替换元素
  4. 常规流中的块级替换元素
  5. 浮动的非替换元素
  6. 浮动的替换元素
  7. 绝对定位的非替换元素
  8. 绝对定位的替换元素
  9. 常规流中非替换的'inline-block'元素
  10. 常规流中替换的'inline-block'元素

对于1-6和9-10条,'top'和'bottom'的应用值由9.4.3节的规则确定

注意:这些规则同样适用于根元素,像其它元素一样

注意 下面计算的'height'的应用值是一个初步值,可能不得不经多次计算,取决于'min-height''max-height',见下面的最小、最大高度章节

10.6.1 行内非替换元素

'height'属性不适用。内容区(content area)的高度应该基于字体,但本规范没有具体说明。例如,UA可以使用em框(em-box)或者字体的最大上伸部(ascender)和下延部(descender)(后者能够确保em框上方或者下方的字形(glyph)仍处于内容区里,但会导致不同字体有不同大小的盒;前者能够确保编写者可以相对于'line-height'控制背景样式化,但会导致字形绘制在其内容区外)

注意:CSS 3可能会包含用来选择用于内容高度的字体测量方法的属性

行内非替换盒的垂直内边距,边框和外边距从内容区的顶部和底部开始,并且与'line-height'无关。'line-height'只在计算行框的高度时使用

如果应用了多个字体(发现字形是多种字体时会发生这种情况),内容区的高度不由本规范定义。然而,我们建议高度让内容区刚好放得下元素中的所有字体的(1)em盒或者(2)最大上伸部和下延部。注意,这可能大于所有涉及的字体(的高度),取决于字体的基线对齐方式

10.6.2 常规流中的行内替换元素,块级替换元素,替换的inline-block元素和浮动替换元素

如果'margin-top'或者'margin-bottom'为'auto',其应用值为0

如果'height''width'的计算值都是'auto',并且元素还具有固有高度,那么这个固有高度就是'height'的应用值

否则,如果'height'的计算值为'auto',并且该元素具有固有比例,那么'height'的应用值为:

(宽度的应用值) / (固有比例)

否则,如果'height'的计算值为'auto',并且该元素具有固有高度,那么这个固有高度就是'height'的应用值

否则,如果'height'的计算值为'auto',但上面的条件都不满足,那么'height'的应用值必须设置为比例为2:1,高度不超过150px并且宽度不超过设备宽度的最大矩形的高度

10.6.3 当'overflow'计算值为'visible'时常规流中的块级非替换元素

本节也适用于常规流中的块级不可替换元素,当'overflow'的计算值不为'visible'但已经传播到视口时

如果'margin-top''margin-bottom'为'auto',则其应用值为0。如果'height'为'auto',高度取决于该元素是否含有块级子级以及是否具有padding或border:

该元素的高度为从其内容上边界到下面第一个适用的(位置)的距离:

  1. 最后一个行框的下边界。如果该盒为一行或多行建立了一个行内格式化上下文的话
  2. 它的最后一个流内子级的下外边距(可能被合并了)的下边界。如果该子级的下外边距没有和该元素的下外边距合并的话
  3. 最后一个流内子级的下边框边界。如果其上外边距不与该元素的下外边距合并的话
  4. 否则,为0

只考虑常规流中的子级(即,浮动盒和绝对定位的盒会被忽略,并且相对定位的盒不考虑其偏移)。注意子级盒可以是一个匿名块盒

10.6.4 绝对定位的非替换元素

就本节和下一节而言,术语(一个元素的)"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条合适的应用

  1. 如果'top'和'height'都是'auto','bottom'不是'auto',则高度是根据10.6.7由内容决定,把值为'auto'的'margin-top'和'margin-bottom'设置为0,再求出'top'
  2. 如果'top'和'bottom'都是'auto','height'不是'auto',则把'top'设置为静态位置,把值为'auto'的'margin-top'和'margin-bottom'设置为0,再求出'bottom'
  3. 如果'height'和'bottom'都是'auto','top'不是'auto',则高度根据10.6.7由内容决定,把值为'auto'的'margin-top'和'margin-bottom'设置为0,再求出'bottom'
  4. 如果'top'是'auto','height'和'bottom'都不是'auto',则把值为'auto'的'margin-top'和'margin-bottom'设置为0,再求出'top'
  5. 如果'height'是'auto','top'和'bottom'都不是'auto',则把值为'auto'的'margin-top'和'margin-bottom'设置为0,再求出'height'
  6. 如果'bottom'是'auto','top'和'height'都不是'auto',则把值为'auto'的'margin-top'和'margin-bottom'设置为0,再求出'bottom'

10.6.5 绝对定位的替换元素

这种情况与前一种类似,只是(expect that)元素具有固有高度。步骤(sequence)替换为:

  1. 'height'的应用值由行内替换元素决定。如果'margin-top'或者'margin-bottom'被指定为'auto',其应用值就由下面的规则决定
  2. 如果'top''bottom'都是'auto',把'top'换成该元素的静态位置
  3. 如果'bottom'是'auto',把所有值为'auto'的'margin-top'或者'margin-bottom'换成'0'
  4. 如果此时'margin-top''margin-bottom'仍然都是'auto',解方程时要添上额外的约束:2个margin值必须相等
  5. 如果此时只剩下一个'auto'了,解方程求出这个值
  6. 如果此时该值被过度约束了,就忽略'bottom'的值再求出这个值

10.6.6 复杂情况

本节适用于:

如果'margin-top'或者'margin-bottom'为'auto',其应用值为0。如果'height'是'auto',高度取决于该元素的后代,根据10.6.7

对于'inline-block'元素,在计算行框的高度时,使用外边距框(margin box)

10.6.7 块格式化上下文中的'Auto'高度

特定情况下(例如,见上面的10.6.4节和10.6.6节),一个建立了块格式化上下文的元素的高度按照如下规则计算:

如果它只含有行内级子级,高度就是最高的行框的顶端与最低的行框的底端之间的距离

如果它只含有块级子级,高度就是最高的块级子级盒的上外边距边界到最低的块级子级盒的下外边距边界之间的距离

绝对定位的子级会被忽略,并且相对定位的盒不考虑其偏移。注意,子级盒可以是一个匿名块盒

此外,如果该元素含有任意下外边距边界位于元素的内容下边界下方的的浮动后代,那么高度增加至能够包含这些边界。只考虑参与此块级格式化上下文的浮动,例如,不考虑绝对定位的后代中的浮动或其它浮动

10.7 最小、最大高度'min-height''max-height'

有时把元素的高度约束到一个特定范围很有用。两个属性提供了这种功能:

'min-height'
Value:  <length> | <percentage> | inherit
Initial:  0
Applies to:  除非替换的行内元素,表格列和列组(column group)外的所有元素
Inherited:  no
Percentages:  见下文
Media:  visual
Computed value:  与指定值相同的百分比,或者绝对长度
'max-height'
Value:  <length> | <percentage> | none | inherit
Initial:  none
Applies to:  除非替换的行内元素,表格列和列组(column group)外的所有元素
Inherited:  no
Percentages:  见下文
Media:  visual
Computed value:  与指定值相同的百分比或者绝对长度或者'none'

这两个属性允许编写者把盒的高度约束到一个特定范围。值含义如下:

<length>
指定一个固定的最小或者最大计算高度(computed height)
<percentage>
指定一个用来确定应用值的百分比。百分比根据生成盒的包含块的高度来计算。如果包含块的高度不是显式指定的(即,取决于内容高度),并且该元素不是绝对定位的,百分比值会被当作'0'(对于'min-height')或者'none'(对于'max-height'
none
(只对'max-height'有效)对盒的高度没有限制

负值对'min-height''max-height'是非法的

CSS 2.1中,'min-height'和'max-height'对表格,行内表格,表格单元,表格行和行组(row group)的效果是未定义的

如下算法描述了这两个属性怎样影响'height'属性的应用值

  1. 计算初步的应用高度(不考虑'min-height''max-height')遵循上面“计算height与margin”中的规则
  2. 如果这个初步高度大于'max-height',就再应用一遍上面的规则,但这次把'max-height'的值作为'height'的计算值
  3. 如果产生的高度小于'min-height',就再应用一遍上面的规则,但这次把'min-height'的值作为'height'的计算值

这些步骤不会影响以上属性真实的计算值,'height'应用值的变更不会影响外边距合并,除了在“合并外边距(8.3.1)”中特别提到的关于'min-height'或者'max-height'的规则

然而,对于'width''height'的计算值为'auto'的替换元素,就用上面的最小、最大宽度中的算法来算出宽度和高度的应用值。然后把产生的宽度和高度作为计算值再应用上面的“计算height与margin”中的规则

10.8 行高的计算'line-height''vertical-align'属性

行内格式化上下文节所述,用户代理把行内级盒排列在一个行框的垂直堆叠里。行框的高度由下列规则决定:

  1. 计算行框中每个行内级盒的高度时,对于替换元素,inline-block元素和inline-table元素,这个值就是其外边距框(margin box)的高度;对于行内盒,这个值是其'line-height'(见“计算height与margin”“行距(Leading)与半行距”中的行内盒的高度
  2. 行内级盒是根据其'vertical-align'属性垂直对齐的。如果它们是'top'或者'bottom'对齐,它们必须对齐得让行框高度最小化。如果这样的盒足够高,存在多个解,而CSS 2.1没有定义行框基线的位置(即,strut的位置,见下文)
  3. 行框高度是最高的盒的顶端与最低的盒的底端之间的距离(包括下面'line-height'中解释的strut

空行内元素生成空的行内盒,但这些盒仍然具有margin,padding,border和line height,从而影响这些计算,就像有内容的元素一样

10.8.1 行距(Leading)与半行距

CSS假定任何字体都具有指定了基线上方的高度(height)和下方的深度(depth)特征的字体规格(font metrics)。本节中,我们用A表示高度(对于一个给定大小的指定字体),D表示深度。我们还定义了AD = A + D,表示从顶端到底端的距离(见下面对如何找出TrueType和OpenType字体的AD的注释)。注意,这些都是字体整体的规格,并没有与所有单个字形的上伸部(ascender)和下延部(descender)对应

用户代理必须把一个非替换的行内盒中的字形彼此之间按其相关基线对齐,然后,对每个字形,确定AD。注意单一元素中的字形可能来自不同的字体,并且因此不一定具有相同的AD。如果行内盒不含任何字形,就认为它含有一个strut(一个不可见的0宽字形),它具有该元素的第一个可用字体的AD

然后对每个字形,确定要添加的行距(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"规格

'line-height'
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'指定的高度用来计算行框高度

属性值含义如下:

normal
告诉用户代理根据该元素的字体把应用值设置为一个“合理的”值。该值与<number>的含义相同。我们推荐介于1.0到1.2的“常规”应用值。计算值为'normal'
<length>
指定的长度用来计算行框的高度。负值是非法的
<number>
该属性的应用值为这个数字乘以该元素的字体大小。负值是非法的。计算值与指定值相同
<percentage>
该属性的计算值为这个百分比乘以该元素的字体大小的计算值。负值是非法的

示例:

下例的这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'。在不得不对齐字体不同的文本列时,这一点很重要,例如在表格中

'vertical-align'
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)

baseline
把盒的基线与父级盒的基线对齐。如果该盒没有基线,就把下外边距边界和父级的基线对齐
middle
把该盒的垂直中点与父级盒的基线加上父级的半x-height对齐
sub
把该盒的基线降低到合适的位置作为父级盒的下标(该值不影响该元素文本的字体大小)
super
把该盒的基线提升到合适的位置作为父级盒的上标(该值不影响该元素文本的字体大小)
text-top
把该盒的顶端和父级的内容区(content area)的顶端对齐(见10.6.1
text-bottom
把该盒的底端和父级的内容区的底端对齐(见10.6.1
<percentage>
把该盒提升(正值)或者降低(负值)这个距离('line-height'值的百分比)。值'0%'表示与“基线”相同
<length>
把该盒提升(正值)或者降低(负值)这个距离。值'0cm'表示与“基线”相同

下面的值让元素相对于一个行框对齐。因为该元素可能具有相对于它对齐的子级(相应的,(这些子级也)可能具有相对于它们对齐的后代),这些值使用对齐子树的边界(the bounds of the aligned subtree)。行内元素的对齐子树包括这个元素和所有'vertical-align'的计算值不为'top'或者'bottom'的子级行内元素的对齐子树。对齐子树的顶端是子树中盒的顶端最高的(位置),底端(的定义)与之类似

top
把对齐子树的顶端与行框的顶端对齐
bottom
把对齐子树的底端与行框的底端对齐

'inline-table'(盒)的基线是表格第一行的基线

'inline-block'(盒)的基线是它的最后一个常规流中的行框的基线,除非它没有流内行框或者其'overflow'属性的计算值不为'visible',此时基线是下外边距边界