CSS 视觉可视化模型

https://www.w3.org/html/ig/zh/wiki/CSS2/visuren

视口 Viewport

在连续媒介上工作的用户代理通常会向用户提供一个视口(屏幕上的一个窗口或其它可视区域),用户可以通过它来访问文档。用户代理可以在视口被调整大小时改变文档的布局(详见初始包含块)。

包含块 Containing blocks

在CSS 2.1中,许多框的位置和大小都根据一个名为包含块的矩形框边缘来相对计算得到。
为元素生成的框通常会充当其后裔框的包含块;我们称框为其后裔“创建”(establishes)了包含块。“框的包含块”表示“框所处的包含块”,而不是其产生的包含块。

The position and size of an element’s box(es) are sometimes calculated relative to a certain rectangle,
called the containing block of the element. The containing block of an element is defined as follows:

  • The containing block in which the root element lives is a rectangle called the initial containing block. For continuous media,
    it has the dimensions of the viewport and is anchored at the canvas origin; it is the page area for paged media. The ‘direction’
    property of the initial containing block is the same as for the root element.
  • For other elements,
    • if the element’s position is ‘relative’ or ‘static’, the containing block is formed by the content edge of the nearest block container ancestor box(最近代的块容器框).
    • If the element has ‘position: fixed’, the containing block is established by the viewport in the case of continuous media or the page area in the case of paged media.
    • If the element has ‘position: absolute’, the containing block is established by the nearest ancestor with a ‘position’ of ‘absolute’, ‘relative’ or ‘fixed’, in the following way:
      1. In the case that the ancestor is an inline element, the containing block is the bounding box around the padding boxes of the first and the last inline boxes generated for that element. In CSS 2.1, if the inline element is split across multiple lines, the containing block is undefined.
      2. Otherwise, the containing block is formed by the padding edge of the ancestor.
  • If there is no such ancestor, the containing block is the initial containing block.

渲染的步骤就是
1. 为元素创建盒子(generate box)
1. 摆放盒子(position)。摆放盒子的时候,要考虑盒子的类型(块级框、行内级框、行内框),不同的类型有不同的规则。

框(或叫盒)(boxes)的生成

块级元素和块框 Block-level elements and block boxes

块级元素是源文件中会被格式化成块状(例:段落)的元素。’display’属性的以下取值会让一个元素成为块级元素:’block’、’list-item’、’table’。

块级框是参与块格式化上下文的框。每个块级元素生成一个主要的块级框来包含其子框和生成的内容,同时任何定位方案都会与这个主要的框有关。某些块级元素还会在主要框之外产生额外的框:例如“list-item”元素。这些额外的框会相对于主要框来放置。

除了table框,和可替换元素,一个块级框同时也是一个块容器框,一个块容器框要么只包含块级框,要么创建一个行格式化上下文而只包含行内级框。并非所有的块容器框都是块级框(即意味着此块容器框不是以的形式在其容器框中定位):不可替换的行内块和不可替换的table cell也是块容器但不是块级框。是块级框的块容器称作块框

块容器盒要么只包含行内级盒,要么只包含块级盒。但通常文档会同时包含两者。在这种情况下,将创建匿名块盒来包含毗邻的行内级盒。换句话说:如果一个块容器框有一个块级框,那么我们强制它只包含块级框在其中,行内框被“匿名框”围绕。

另一种将创建匿名块盒的情况是,一个行内盒包含了一个或几个块盒。在这种情况下,包含块盒的盒将拆分为两个行内盒放置于块盒前后,然后分别由两个匿名块盒包含。这样块盒就与两个包含行内元素的匿名块盒形成了兄弟关系。

三个术语:块级框(block-level box)、块容器框(block container box)和块框(block box)在意义明确的时候简称为块(block)。

行内级元素和行内框 Inline-level elements and inline boxes

行内级元素是源文档中那些不为其内容形成新的块,而让其内容分布在多行中的元素(如,段落内着重的文本,行内图形等等)。
以下的’display’属性值产生一个行内级元素:’inline’, ‘inline-table’, and ‘inline-block’。
行内级元素生成行内级框,而这些框会参与某个行内格式化上下文。

一个行内框是行内级框,且其内容参与了包含它的行格式化上下文。一个’display’值是’inline’的非替换元素会生成一个行内框。
那些不是行内框行级框(例如可替换的行级元素、行内块元素、行内表格元素)被称为原子行内级框
因为它们是以单一不透明框Template:Extra not的形式来参与其行内格式化上下文。

对比

  • 块级框、块容器框、块框 vs 行内级框、行内框、行框
  • 块级框和块框 与 行内级框和行框 的定义方式不同
  • 块级框参于块格式化上下文,行内级框参与行格式化上下文。行内框内容也参与行格式化上下文。
  • 块框是由某个元素直接产生的,行内框是由某个元素直接产生的,行框不是由某个元素直接产生,而是由多个元素共同作用产生的。

定位方案 positioning schemes

当创建好盒子后,这些盒子如何摆放呢?要决定如何摆放,就有了“定位方案”;

  1. Normal flow 常规流
  2. Float 浮动
  3. absolutely position 绝对定位

Normal flow 常规流

formatting contexts

在常规流定位方案中,需要一些变量信息来决定元素的定位,formatting context就是记录这些信息的东西。

框在正常排版中必然属于一个格式化上下文,要么是块格式化上下文,要么是行格式化上下文。块级框参与块格式化上下文。行级框参与行格式化上下文。

block formatting context 就是盒子要按照block的规则摆放,相应的,inline formatting context 就是盒子要按照inline的规则摆放。

那何时创建或改变这个context呢?

  • 有这几种框会为其内容创建新的block formatting context:根元素浮动框绝对定位框inline-blockstable cellstable captions‘overflow’属性为非’visible’的块元素display: flow-root
  • the inline formatting context is triggered when a block container box contains only inline elements. 如果块容器框包含块元素和行内元素,那行内元素会被包围在匿名块中,从而块容器(匿名块)仅包含这个行内元素。

Block formatting context的规则 :

  1. 框会从包含块的顶部开始,一个接一个地,垂直向下地摆放。两个兄弟框之间的垂直距离由 ‘margin’ 属性来决定。在同一个块格式化上下文中,相邻的块级框之间的垂直外边距会出现折叠。
  2. 每个框的左外边距边要紧贴其包含块的左边。即使在有浮动的情景下也是如此 (although a box’s line boxes may shrink due to the floats),除非框创建了一个新的块格式化上下文(在这种情况下该框可能会为了避开浮动框而变窄)。
  3. 当处理百分比值时,应该忽略匿名块框,而以其最近的非匿名祖先框来替代。例如,如果一个匿名块框的孩子在DIV里面需要知道包含块的高度来解析一个百分比高度,那么它将使用DIV形成的包含块的高度,而不是匿名块框的高度。

Inline formatting contexts的规则:

  1. 在行格式化上下文中,框会从包含块的顶部开始,一个接一个地水平摆放。摆放这些框的时候,它们在水平方向上的外边距、边框、内边距所占用的空间都会被考虑在内。
  2. 在垂直方向上,这些框可能会以不同形式来对齐:它们可能会把底部或顶部对齐,也可能把其内部的文本基线对齐。能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框。
  3. 通常,行框的左边紧贴其包含块的左边,而行框的右边紧贴其包含块的右边。然而,浮动框可以插在包含块边缘与行框边缘之间。因此,尽管在同一个行内上下文中的行框通常有同样的宽度(也就是其包含块的宽度),但它们的宽度也可能受浮动让水平可用空间减少的影响而有所改变。在同一个行格式化上下文中,行框的高度通常是变化的(例如:某一行包含了一个比较高的图片,而其它行只包含文本)。
  4. 当一行上的行级框的总宽度小于包含它们的行框的宽度,则它们在行框内的水平分布由’text-align’属性来决定。如果该属性取值为’justify’,则用户代理可拉伸行内框(但不能是inline-table和inline-block框)中的空格和字间距。
  5. 当一个行内框的宽度超过了行框的宽度,则它会被分割成几个框,而这些框会分布在几个行框。如果此行内框不可分割(例如:单个字符、或语言指定的文字打断规则不允许在此行内框中出现打断、或该行内框受white-space属性为nowrap或pre的影响),那么该行内框溢出该行框。 input等不是行内框而是行内级框,其内容不参与行格式化上下文,故不能被分割。
  6. 行内框被分割的时候,外边距、边框和内边距在出现分割的地方都没有视觉效果。

块级元素有两个职责:定位和格式化内容。

当用来定位时,块级元素扮演“块级框”的角色。(When dealing with positioning,
a block-level element acts as a “block-level box”.)

当用来格式化内容时,块级元素扮演“块容器”的角色。(When dealing with formatting,
a block-level element acts as a “block container box”.)

Acting as a “block-level box”, the block-element behaves according to the type of
positioning (static, absolute, relative, fixed) specified by the position property.

Acting as a “block container box”, the block-element establishes a block-formatting
context if the block-element has at least one child block-level element. If all the
child elements are inline-level boxes, then an inline-formatting context is established.
注意,这里仅仅是指作为“块容器框”时的一个职责是创建块格式化上下文,并非指作为“块容器框”时一定会
创建块格式化上下文。创建块格式化上下文的条件参考上文。

Float 浮动

在当前行向左或右偏移的框就是浮动框。浮动框最有趣的特点是其它内容可以紧挨着它的一侧来排版 (也可以通过’clear’属性来禁止这样排版)。
内容会紧挨着左浮框的右侧排版,而紧挨着右浮框的左侧排版。

一个浮动框会向左或向右进行偏移直到其外边缘紧贴其包含块的边缘或另一个浮动框的外边缘。如果摆放浮动框时,当前行已有一个行框,则浮动框的顶部外边缘会与该行框的顶部对齐。

如果因当前行剩余水平空间不足而放不下一个浮动框,则该浮动框会下移,直到找到放得下它的位置或者当前位置以下已没有更多浮动出现。

因为浮动不属于正常排版流(flow),在浮动框前面和后面被创建的非定位块框会如同该浮动不存在一样地垂直排版。
但是,当前和随后的紧挨着浮动框被创建的行框,会按需要缩短其宽度来为浮动框的外边距框让出空间。

如果被缩短后的行框过小,以至于它无法容纳任何内容,则应使该行框下移(并重新计算其可用宽度),直到它能容纳一些内容,或其下方已无其它浮动框。
当前行中位于浮动框前面的任何内容要在浮动的另一边重新排版。换句话说,如果已有行级框摆放入当前行,再遇到一个左浮框可放入行框剩余的空间,则该左浮框会摆放在该行,
并与行框顶部对齐,然后之前已放入行框内的行内框会被移到该左浮框的右边(右边算是左浮框的另一边)重新摆放。

绝对定位 Absolute positioning

绝对定位元素(或它的框):该元素的’position’属性设置为’absolute’或’fixed’。在绝对定位模型中,一个框基于它的包含块而显式地偏移。它完全从正常排版中脱离(对后继的兄弟没有影响)
一个绝对定位框为它的正常排版子元素和绝对地定位(不是fixed)后代生成一个新的包含块。
不过,绝对定位元素的内容不会在其它框的周围排列。它们可能会也可能不会挡住另外一个框的内容(或者被挡住),这取决于互相重合的框的堆叠层次。

固定定位 Fixed positioning

固定定位是绝对定位的一个子类。
唯一的区别是,对于固定定位框,它的包含块由视口创建。
对于连续媒介,固定框并不随着文档的滚动而移动。从这个意义上说,它们类似于固定的背景图形。
对于页面媒介,固定定位框在每页里重复。
需要在每一页底部放置一个签名时,这个方法很有用。
如果一个固定定位框的大小大于整个页面的大小,多余的部分会被裁切(而不是滚动)。

‘display’、’position’ 与 ‘float’ 的关系 Relationships between ‘display’, ‘position’, and ‘float’

影响框的生成和布局的三个属性——’display’,’position’和’float’——间的相互关系如下:
1. 如果’display’值为’none’,那么’position’和’float’无效,元素不生成框。
1. 否则,如果’position’值为’absolute’或者’fixed’,框绝对地定位’float’计算的值为’none’,并且 display根据下面的表格进行设定。框的位置由’top’, ‘right’, ‘bottom’和’left’属性和包含块决定。
1. 否则,如果’float’的值不是’none’,该框是浮动的,且’display’值根据下面的表格进行设定。
1. 否则,如果元素是根元素,’display’值根据下面的表格进行设定,除了其在CSS2.1里面没有定义是否指定值’list-item’对应计算值’block’或者’list-item’。
否则,’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 block
其他 与指定值相同

发表评论

电子邮件地址不会被公开。