WebCore 渲染 IV – 绝对/固定定位与相对定位

CSS 中的 position 属性可以用于将对象相对于特定的包含块定位。它有四个值:‘static’、‘absolute’、‘fixed’ 和 ‘relative’。静态定位是默认值,意味着对象仅根据块和行布局的正常规则进行定位。

相对定位

相对定位与静态定位完全相同,不同之处在于可以使用 CSS 的 lefttoprightbottom 属性来对对象应用平移。isRelPositioned 方法可以用于查询渲染器是否正在使用相对定位。

bool isRelPositioned() const

可以使用以下方法获取将应用的平移偏移量

int relativePositionOffsetX() const;
int relativePositionOffsetY() const;

相对定位实际上仅仅是绘制时的平移。就布局而言,对象仍在其原始位置。下面是一个使用相对定位将行的一部分向上移动几个像素的示例。如您所见,行的布局就像对象处于原始位置一样。

<div style="border:5px solid black; padding:20px; width:300px">
Here is a line of text.
<span style="position:relative;top:-10px; background-color: #eeeeee">
This part is shifted<br> up a bit,
</span>
but the rest of the line is in its original position.
</div>
这是一行文本。 这部分向上
移动了一点
,但行的其余部分仍在其原始位置。

绝对定位和固定定位

固定定位的对象是相对于视口定位的,即浏览器窗口的可见页面区域。绝对定位的对象是相对于其包含块定位的,包含块是最近的、position 属性值非‘static’的祖先块。如果不存在这样的块,则使用初始包含块 (RenderView)。有关包含块的更多详细信息,请参阅上一篇文章。

isPositioned 方法可用于判断渲染器是绝对定位还是固定定位。

bool isPositioned() const

当一个对象被绝对/固定定位时,它会变为块级元素。即使 CSS display 类型设置为 inline(或 inline-block/table),一旦对象被定位,其有效的 display 类型就会变为块级。对于已定位的元素,isInline 方法将返回 false。

RenderStyle 可以提供两种 display 值。有时原始 display 类型是相关的且布局需要,可以使用以下方法获取这两种 display 类型。

EDisplay display() const;
EDisplay originalDisplay() const;

定位对象列表

每个块都有一个定位对象列表,其中包含所有以其为包含块的绝对/固定定位渲染器。放置这些定位子元素是块的职责。以下方法可用于操作定位对象列表

void insertPositionedObject(RenderObject*);
void removePositionedObject(RenderObject*);

layoutOnlyPositionedObjects 方法用于只布局块的定位对象。如果只有定位对象发生了变化,则此方法返回 true。这表明 layout 方法不必布局其任何正常子元素,并且可以提前返回。

bool layoutOnlyPositionedObjects

layoutPositionedObjects 方法负责定位对象的放置。它接受一个布尔参数,指示是否应强制对所有对象进行重新布局。在各种情况下可能需要重新布局,这将在未来的文章中介绍。

bool layoutPositionedObjects(bool relayoutChildren)

定位对象的坐标

CSS 中定位对象的坐标是相对于包含块的内边距边缘。例如,为绝对定位对象指定 (0, 0) 的 left 和 top 位置将导致对象恰好放置在包含块的左上边框内部。这是一个示例

<div style="position:relative;border:5px solid black;width:300px;height:300px;">
<div style="position:absolute;width:200px;height:200px;background-color:purple"></div>
</div>

在 WebCore 中,坐标位置始终是相对于边框边缘的,因此在上面的示例中,对象实际上位于 (5, 5)。

当 CSS 中省略所需的坐标时,WebCore 必须为定位对象确定一个合适的位置。CSS 对此有一套极其复杂的规则,我们将在未来的文章中更详细地探讨。

行内相对定位容器

相对定位的行内元素可以作为绝对定位后代的“包含块”。这是另一个极其复杂的边界情况,值得单独写一篇文章。目前,只需知道这种构造是可能的,并且代码确实必须处理它。