层叠样式表第2级 CSS2规范开发手册 - WEB前端开发 专注前端开发,关注用户体验

10 可视化格式模型的细节

    目录

10.1 “包含块”的定义

    一个元素的框的尺寸和位置的计算有时相对于某个特定的长方形,称为该元素的包含块。一个元素的包含块的定义如下:

  1. 根元素存在的包含块(出事包含块)由用户端选择。
  2. 对于其它元素,它的包含块由它的最近的块类前辈框创建,除非它是绝对定位的。
  3. 如果元素设置了'position: fixed',包含块由视点创建。
  4. 如果元素设置了'position: absolute',包含块由最近的前辈创建(它的'position'不是'static'),方法如下:
    1. 如果前辈是块类元素,包含块由前辈的边白边形成。
    2. 如果前辈是行内元素,包含块取决于前辈的'direction'属性:
      1. 如果'direction'为'ltr',包含块的顶、左边是该前辈创建的第一个框的顶、左内容边,它的底、右边是该前辈创建的最后一个框的底、右内容边。
      2. 如果'direction'为'rtl',包含块的顶、右边是该前辈创建的第一个框的顶、右内容边,它的底、左边是该前辈创建的最后一个框的底、左内容边。

        如果不存在这样的前辈,根元素框的内容边创建该包含块。

例子:

    不考虑定位,下面文档的包含块(C.B.):

<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.的元素
body初始C.B.(与用户端相关)
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 }

    包含块的表格成为:

产生框的元素 创建C.B.的元素
body初始C.B.
div1初始C.B.
p1div1
p2div1
em1div1
strong1em1

    "em1"定位后,它的包含块成为最靠近的前辈定位框(即,由"div1"创建的那一个)。

10.2 内容的宽度'width'属性

'width'
值:  <length> | <percentage> | auto | inherit
初始值:  auto
适用于:  所有元素,除了行内非替换元素,表格行和行组。
可否继承:  
百分比:  基于包含块的宽度
媒介:  图形

    该属性指定了块类元素和替换元素产生的框的内容宽度

    该元素并不适用于非替换的行内元素。非替换行内元素框的宽度是它们中内容渲染后(在任何子元素相对偏移之前)的宽度。我们应该记得行内框排列在线框内。而线框的宽度由它们的包含块给出,但是可能由于出现浮动而被缩短。

    替换元素的宽度是内在的,并且如果该属性值不是'auto',用户端可能将其重新定比。

    属性值的含义如下:

<length>
指定一个固定宽度。
<percentage>
指定一个百分比宽度。百分比的计算基于生成框的包含块的宽度。
auto
宽度取决于其它属性的值。参加以后的节。

    负的'width'值是非法的。

例子:

    例如,下面的规则将段落的内容宽度固定为100点:

P { width: 100px }

10.3 宽度和边距的计算

    一个元素的'width''margin-left''margin-right''left''right'属性的计算值取决于产生的框的类型,并互相影响。一般而言,计算值和指定值相同,'auto'被某个合适的值取代。不过还是有例外。下面这些情况需要加以考虑:

  1. 行内的非替换元素
  2. 行内的替换元素
  3. 常规流向中的块类、非替换元素
  4. 常规流向中的块类、替换元素
  5. 浮动的非替换元素
  6. 浮动的替换元素
  7. 绝对定位的非替换元素
  8. 绝对定位的替换元素

    1-6包括相对定位。

10.3.1 行内的非替换元素

    'width'属性不适用。对'left''right''margin-left''margin-right'指定'auto'的效果是计算值为'0'。

10.3.2 行内的替换元素

    对'left''right''margin-left''margin-right'指定'auto'的效果是计算值为'0'。指定'width'为'auto'将元素的内在宽度赋给计算值。

10.3.3 常规流向中的块类、非替换元素

    如果'left''right'设置为'auto',它们的计算值为0。在其它属性间必须保持下面的约束

    'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = 包含块的宽度

    (如果边框的样式为'none',边框宽度认为是'0'。)如果上述所有的属性指定了非'auto'的值,这些值被称为是“过度约束”,其中之一的计算值将不得不和它的指定值不同。如果'direction'属性为'ltr','margin-right'的指定值被忽略,并重新计算以满足上面的等式。如果'direction'为'rtl',对'margin-left'采取上述的方法。

    如果只有一个值指定为'auto',它的计算值从等式中得出。

    如果'width'设置为'auto',则其它的'auto'值成为'0'而'width'从等式的剩余部分得到。

    如果'margin-left''margin-right'为'auto',它们的计算值相同。

10.3.4 常规流向中的块类、替换元素

    如果'left''right'为'auto',它们的计算值为0。如果'width'指定为'auto',它的值是元素的内在宽度。如果某一个边距设置为'auto',它的计算值由上述的约束给出。更进一步,如果两个边距都设置了'auto',它们的计算值相等。

10.3.5 浮动的非替换元素

    如果'left''right''width''margin-left''margin-right'指定为'auto',它们的计算值为'0'。

10.3.6 浮动的替换元素

    如果'left''right''margin-left''margin-right'指定为'auto',它们的计算值为'0'。如果'width'为 'auto',它的值是元素的内在宽度。

10.3.7 绝对定位的非替换元素

    确定这些元素计算值的约束为:

    'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = 包含块的宽度

    (如果边框样式为'none',边框宽度认为是'0'。这一约束的实现通过如下顺序的一系列替换而达到:

  1. 如果'left'设置为'auto'而'direction'为'ltr',替换'auto'为:包含块左边到假定它的'position'属性设置为'static',而生成元素的第一个框的那个假想框的左边距边的距离。(但是为了不去实际计算那个框,用户端可以自由地猜想它可能在的位置。)如果假想框在包含块的左边,该值为负数。
  2. 如果'right'设置为'auto'而'direction'为'rtl',替换'auto'为:包含块右边到上述提到的那个假想框的右边距边的距离。如果假想框在包含块边的左边,该值为正数。
  3. 如果'width'为'auto',将剩余'left''right'的'auto'替换为'0'。
  4. 如果'left''right''width'还是'auto',将所有'margin-left''margin-right'的'auto'替换为'0'。
  5. 如果在这一步'margin-left''margin-right'还是'auto',基于额外的约束即两个边距必须相同,解出等式。
  6. 如果在这一步只有一个'auto'存在,根据等式解出那个值。
  7. 如果在这一步各值间过度约束,要么忽略'left'的值(如果'direction'为'rtl'),要么忽略'right'的值(如果'direction'为'ltr'),然后解出那个值。

10.3.8 绝对定位的替换元素

    这一情况和前一情形类似,但是元素有一个内在宽度。替换的顺序是:

  1. 如果'width'为'auto',替换为元素的内在宽度。
  2. 如果'left'设置为'auto'而'direction'为'ltr',替换'auto'为:包含块左边到假定它的'position'属性设置为'static',而生成元素的第一个框的那个假想框的左边距边的距离。(但是为了不去实际计算那个框,用户端可以自由地猜想它可能在的位置。)如果假想框在包含块的左边,该值为负数。
  3. 如果'right'设置为'auto'而'direction'为'rtl',替换'auto'为:包含块右边到上述提到的那个假想框的右边距边的距离。如果假想框在包含块边的左边,该值为正数。
  4. 如果'left''right'是'auto',将所有'margin-left''margin-right'的'auto'替换为'0'。
  5. 如果在这一步'margin-left''margin-right'还是'auto',基于额外的约束即两个边距必须相同,解出等式。
  6. 如果在这一步只有一个'auto'存在,根据等式解出那个值。
  7. 如果在这一步各值间过度约束,要么忽略'left'的值(如果'direction'为'rtl'),要么忽略'right'的值(如果'direction'为'ltr'),然后解出那个值。

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

'min-width'
值:  <length> | <percentage> | inherit
初始值:  取决于用户端
使用于:  所有元素,除了非替换行内元素和表格元素
可否继承:  
百分比:  基于包含块的宽度
媒介:  图形
'max-width'
值:  <length> | <percentage> | none | inherit
初始值:  none
适用于:  所有元素,除了非替换行内元素和表格元素
可否继承:  
百分比:  基于包含块的宽度
媒介:  图形

    这两个属性允许作者将框的宽度限制在一个确定的范围内。取值的含义如下:

<length>
指定一个固定的最小和最大的计算宽度。
<percentage>
指定确定计算值的百分比。百分比的计算基于生成框的包含块的宽度。
none
(仅用于'max-width')对框的宽度没有限制。

    下面的算法描述了这两个属性如何影响'width'属性的计算值

  1. 先根据上述“宽度和边距的计算”中的规则计算宽度(不考虑'min-width''max-width')。
  2. 如果计算得到的'min-width'大于'max-width''max-width'设置为'min-width'的值。0
  3. 如果计算值大于'max-width'上述规则再次使用,但是这次用'max-width'作为'width'的指定值。
  4. 如果计算值小于'min-width'上述规则再次使用,但是这次用'min-width'作为'width'的指定值。

    用户端可以指定一个非负的'min-width'属性的最小值,该值根据不同的元素,甚至根据其它属性而不同。如果'min-width'小于该下限,或者是因为它显式地指定,或者是它设置为'auto'而其后的规则使它变得太小,用户端可以使用最小值作为计算值。

10.5 内容的高度'height'属性

'height'
值:  <length> | <percentage> | auto | inherit
初始值:  auto
适用于:  所有元素,除了非替换行内元素,表格列和列组
可否继承:  
百分比:  见描述
媒介:  图形

    该属性指定了块类元素和替换元素生成的框的内容高度

    本属性不适用于非替换行内元素。非替换行内元素框的高度由元素的'line-height'值(或继承值)决定。

    取值的含义如下:

<length>
指定固定的高度。
<percentage>
指定一个百分比高度。百分比的计算基于生成框的包含块的高度。如果包含块的高度没有显式给出(即,它取决于内容的高度),该值等同于'auto'。
auto
高度取决于其它属性。见下面的描述。

    负的'height'值是非法的。

例子:

    例如,下面的规则将段落的高度固定为100点:

P { height: 100px }

    高度超过100点的段落将根据'overflow'属性而产生溢出

10.6 高度和边距的计算

    在计算'top', 'margin-top''height''margin-bottom''bottom'的值时,必须对不同种类的框加以区别:

  1. 行内的非替换元素
  2. 行内的替换元素
  3. 常规流向中的块类、非替换元素
  4. 常规流向中的块类、替换元素
  5. 浮动的非替换元素
  6. 浮动的替换元素
  7. 绝对定位的非替换元素
  8. 绝对定位的替换元素

    1-6包含相对定位。

10.6.1 行内的非替换元素

    如果'top''bottom''margin-top''margin-bottom'为'auto',它们的计算值为0。'height'属性并不适用,但是框的高度由'line-height'属性给出。

10.6.2 行内的替换元素,常规流向中的块类、替换元素,浮动的替换元素

    如果'top''bottom''margin-top''margin-bottom'为'auto',它们的计算值为0。如果'height'为'auto',则计算值为内在高度。

10.6.3 常规流向中的块类、非替换元素,浮动的非替换元素

    如果'top''bottom''margin-top''margin-bottom'为'auto',它们的计算值为0。如果'height'为'auto',高度取决于该元素是否有任何块类子元素。如果它只包含行内子元素,高度等于最顶端的线框的顶到最底端的线框的底之间的距离。如果它包含块类子元素,高度等于最顶端的块类子框的顶边界到最底端的块类子框的底边界。只考虑常规流向中的子元素(即,浮动框和绝对定位框被忽略,只考虑相对定位框未偏移的情况)。注意,子框可以是一个匿名框

10.6.4 绝对定位的非替换元素

    对于绝对定位的元素,垂直方向的尺寸必须满足如下约束:

    'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = 包含块的高度

    (如果边框样式为'none',认为宽度是'0'。)该约束的实现基于下列顺序的一系列替换:

  1. 如果'top'为'auto',将它替换为:包含块的顶边到假定它的'position'属性设置为'static',而生成元素的第一个框的那个假想框的顶边距边的距离。(但是为了不去实际计算那个框,用户端可以自由地猜想它可能在的位置。)如果假想框在包含块上面,该值为负数。
  2. 如果'height''bottom'为'auto',将'bottom'替换为0。
  3. 如果'bottom''height'还是'auto',将'margin-top''margin-bottom'中的'auto'替换为'0'。
  4. 如果在这一步,'margin-top''margin-bottom'还是'auto',根据附加的约束,即这两个边距必须相等来解出等式。
  5. 如果在这一步,只有一个'auto',根据等式解出该值。
  6. 如果在这一步各值间过度约束,忽略'bottom'的值,然后解出那个值。

10.6.5 绝对定位的替换元素

    这一情形和前述类似,只是元素有一个内在高度。替换的顺序变为:

  1. 如果'height'为'auto',将其替换为元素的内在高度。
  2. 如果'top'为'auto',将它替换为:包含块的顶边到假定它的'position'属性设置为'static',而生成元素的第一个框的那个假想框的顶边距边的距离。(但是为了不去实际计算那个框,用户端可以自由地猜想它可能在的位置。)如果假想框在包含块上面,该值为负数。
  3. 如果'bottom'为'auto',将'margin-top''margin-bottom'的'auto'替换为'0'。
  4. 如果在这一步'margin-top''margin-bottom'还是'auto',根据附加的约束,即两个边距必须相等来解出等式。
  5. 如果在这一步只有一个'auto',根据等式解出该值。
  6. 如果在这一步各值间过度约束,忽略'bottom'值,然后根据等式解出那个值。

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

    有时将元素的高度控制在一个特定的范围内很有用。有两个属性提供了这样的功能:

'min-height'
值:  <length> | <percentage> | inherit
初始值:  0
适用于:  所有元素,除了非替换行内元素和表格元素
可否继承:  
百分比:  给予包含块的高度
媒介:  图形
'max-height'
值:  <length> | <percentage> | none | inherit
初始值:  none
适用于:  所有元素,除了非替换行内元素和表格元素
可否继承:  
百分比:  给予包含块的高度
媒介:  图形

    这两个属性允许作者将框的高度限制在一定的范围内。取值含义如下:

<length>
指定一个固定的最小或最大高度。
<percentage>
指定一个百分比来确定计算值。百分比的计算基于生成框的包含块的高度。如果包含块的高度没有显式指定(即,它取决于内容的高度),该百分比值等同于'auto'。
none
(仅对'max-height'适用)对框的高度没有限制。

    下面的算法描述了这两个属性如何影响'height'属性的计算值

  1. 高度的计算基于上述“高度和边距的计算”的规则(不考虑'min-height''max-height')。
  2. 如果'min-height'的计算值大于'max-height''max-height'设置为'min-height'的值。
  3. 如果计算的高度大于'max-height',则上述规则再次使用,但是这次用'max-height'作为'height'的指定值。
  4. 如果计算高度小于'min-height',则上述规则再次使用,但是这次用'min-height'所谓'height'的指定值。

10.8 行高的计算/a>:'line-height''vertical-align'属性

    在行内格式化内容的讨论中,用户端将行内框排列为垂直方向的线框的堆叠。线框高度是这样决定的:

  1. 计算线框内每个行内框的高度(参见“高度和边距的计算”以及'line-height'属性)。
  2. 行内框根据其'vertical-align'属性而在垂直方向对齐。
  3. 线框的高度是最上面的框的顶边到最下面的框的底边的距离。

    空的行内元素产生空的行内框,但是这些框也包括边距,边白,边框和行高,因此和那些有内容的元素一样,影响上述的计算。

    注意,如果线框内所有的框都对齐它们的底部,线框的高度恰好等于最高的框的高度。但是,如果框基于一个共同的基线对齐,线框的顶和底可能接触不到最高的框的顶和底。 box.

10.8.1 差异和半差异

    由于一个行内框的高度会和框内文字的高度有差别(例如,'line-height' > 1em),在渲染的字形符号的上方和下方可能有空白。字体尺寸和'line-height'计算值间的差别就称为差异。差异的一半就称为半差异

    用户端将字形放置在一个行内框的垂直中央,在顶和底加入半差异。例如,如果一段文字高度为'12pt',而'line-height'值为'14pt',则加入2pt的额外空白:1pt在顶部,1pt在底部。(这也适用于空的框,就好象这一空的框包含无限扁的字母。)

    如果'line-height'值小于字体尺寸,最后的行内框的高度将小于字体尺寸,而渲染的字形将“渗出”框的外面。如果这样的一个框接触到一个行内框的边,渲染的字形也会“渗入”相邻的线框。

    虽然非替换元素的边距、边框和边白并不加入行内框高度的计算(也就不参加线框高度的计算),它们还是在行内框周围得到渲染。这就意味着如果一个线框的高度小于框的外边,背景以及边白和边框的颜色可能会“渗入”相邻的线框。不过在这种情况下,有些用户端可能使用线框来“裁剪”边框和边白区域(即,不渲染它们)。

'line-height'
值:  normal | <number> | <length> | <percentage> | inherit
初始值:  normal
适用于:  所有元素
可否继承:  
百分比:  基于元素自身的字体尺寸
媒介:  图形

    如果该属性设置在一个块类元素,而后者的内容由行内元素组成,它指定了每一个生成的行内框的最小高度。

    如果该属性设置在一个行内元素,它指定了该元素生成的每一个框的确切高度。(除了行内替换元素,它的框的高度由'height'属性给出。)

    该属性取值的含义如下:

normal
指示用户端基于元素的字体尺寸将计算值设置为一个“合理”的值。该值的含义和<number>相同。我们推荐'normal'的计算值在1.0到1.2之间。
<length>
框的高度设置到该数值。负数是非法的。
<number>
该属性的计算值是该数字乘以元素的字体尺寸。负数是非法的。不过,该数字而不是计算值将被继承。
<percentage>
该属性的计算值是百分比乘以元素的计算的字体尺寸。负数是非法的。

例子:

    下例的三条规则设置了相同的行高:

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

    注意替换元素有一个'font-size'以及一个'line-height'属性,即使它们并不直接用来确定框的高度。'font-size'用来定义'em'及'ex'单位,而'line-height'在'vertical-align'属性中有一定的作用。

'vertical-align'
值:  baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage> | <length> | inherit
初始值:  baseline
适用于:  行内元素和表格单元元素
可否继承:  
百分比:  基于元素自身的'line-height'
媒介:  图形

    该属性决定一个行内元素产生的框在一个线框内垂直方向的位置。下面的这些值仅在参考父行内元素或(如果该元素生成一个匿名行内框)父块类元素时,有意义;否则它们没有任何作用。

     注意。这些属性的值在表格内容中含义略微有所不同容。请参见表格高度算法以了解更多细节。

baseline
将框的基线对齐父框的基线。如果该框没有基线,将框的底线对齐父的基线。
middle
将框的垂直中间点对齐父框的基线,加上父的x高度的一半。
sub
将框的基线降低到父框的下标的恰当位置。(该值对元素文本的字体尺寸没有影响。)
super
将框的基线升高到父框的上标的恰当位置。(该值对元素文本的字体尺寸没有影响。)
text-top
框的顶对齐父元素字体的顶。
text-bottom
框的底对齐父元素字体的底。
<percentage>
将框升高(正值)或降低(负值)这一距离('line-height'值的百分比)。'0%'等同于'baseline'。
<length>
将框升高(正值)或降低(负值)这一距离。'0cm'等同于'baseline'。

    其它值基于该生成的框所在的线框:

top
框的顶对齐线框的顶。
bottom
框的底对齐线框的底。