1. 苏葳的备忘录首页
  2. 因特网

浏览器的布局

浏览器 布局下来就是浏览器的布局过程。当渲染者被创建并且增加到树上时,它并没有位置和尺寸。计算这些值被称为布局或重排。HTML基于一个流式布局模式,意思是说大多数情况下计算位置会一遍通过。“流”中靠后的元素一般不会影响靠前的元素,所以布局可以沿文档从左到右,从上到下来处理。也有例外—例如,HTML的表格可能需要处理一遍以上。布局时的座标系统基于根框架。使用顶-左座标。

布局是一个递归过程。它起始于根渲染器,对应于HTML文档元素。布局递归的处理完某些或全部框架层次,计算每个渲染者需要的位置信息。

根渲染者的位置是0,0,它的面积大小是视口—浏览器窗口的可见部分。

所有渲染者有一个“layout”或“reflow”方法,每个渲染者调用需要布局的子元素的layout方法。

脏字节系统

为了每次小改动不需要做一次完整布局,浏览器使用一个“脏字节”系统。改动过或增加过东西的渲染者把它自己和子元素标注为“脏”的—需要进行布局。

有两个标识—“脏的”和“子元素是脏的”。子元素是脏的意味着尽管渲染者本身没问题,它却有至少一个子元素需要进行布局。

全局和增量布局

布局可能在整个渲染树上触发—这是“全局”布局。这可能由下述事件造成:

1 影响到所有渲染者的全局样式的改变,象字体大小改变。

2 由屏幕缩放造成。

布局可以是增量的,只有脏的渲染者才会被布置上去(需要额外布局时可能会导致一些损害)。

当渲染者标注为“脏”的时增量布局触发(异步的)。例如来自网络的另外的内容被添加到DOM树后,新的渲染者要添加到渲染树上时。

浏览器的布局

图20:增量布局—只有脏的渲染者和它们的子元素被布局。

异步和同步布局

增量布局会异步的完成。Firefox把增量布局的“重排命令”排入队列,一个任务触发器用来批量执行这些命令。Webkit也有一个定时器执行增量布局—遍历树并且布局那些“脏”渲染者。

脚本请求样式信息,象“offsightHeight”可能会触发同步的增量布局。

全局布局通常会同步触发。

由于某些属性,有时布局会在初始布局之后以回调的形式触发,象滚动位置变化。

优化

当一次布局由“resize”或者渲染者位置(不是尺寸)的改动触发时,渲染者的尺寸从缓存中取得,不会重新计算。

在某些情况下—只有一棵子树修改时,布局不会从根开始。这在改变只发生在区域,不影响到周围的情况下才可能发生—象文本插入了文本域(否则每次键入都会触发从根开始的布局)。

布局过程

布局通常有下列模式:

1 父渲染者决定它自己的宽度

2 父渲染者检查子元素并且:

a 放置子渲染者(设置它的x和y座标)。

b 如果需要的话(它们是“脏”的,或者我们在全局布局模式,或其它一些原因)调用子布局—这会计算出子元素的高度。

3 父渲染者使用子渲染者叠加的高度,和margin及padding的高度来设置它自己的高度—这个值会被父渲染者的父元素使用。

4 设置“脏”标识为假。

Firefox使用一个“state”对象(nsHTMLReflowState)作为布局(以“reflow”命名)的参数。在其它参数中,state包括父元素的宽度。

Firefox的布局的输出是一个“metrics”对象(nsHTMLReflowMetrics)。它里面包含有渲染者计算出的高度。

宽度计算

渲染者的宽度用容器块的width,渲染者样式的“width”属性,margin和border属性等来计算。

例如以下div的宽度:

<div style="width:30%"/>

将会被Webkit象下面这样计算(使用类RenderBox的calcWidth方法):

1 容器宽度是窗口的availableWidth和0之间的最大值。availableWidth在这种情形下是用下列公式计算出的contentWidth:

clientWidth() - paddingLeft() - paddingRight()

clientWidth和clientHeight表示对象内部排除了边框和滚动条后的值。

2 元素宽度是“width”样式属性。它将通过把容器宽度的百分比计算成绝对值来完成。

3 再加上水平border和padding的(宽度)值。

目前计算出了“建议宽度”,现在来计算最小和最大宽度。

如果建议宽度比最大宽度更高,那么会使用最大宽度。如果比最小宽度(最小的不可分割单位)更小,那么使用最小宽度。

以上数值会缓存起来,供宽度未改变而需要布局时使用。

换行

当一个布局中间的渲染者认为需要换行时,它停下来依次通知它的父元素自己需要换行了。父元素会创建另外的渲染者,并对它们调用布局方法。

(待续)

原创文章,作者:苏葳,如需转载,请注明出处:https://www.swmemo.com/2090.html

发表评论

您的电子邮箱地址不会被公开。