Wes*_*rch 32 html css browser rendering-engine repaint
假设我们有一个带有单个样式表的HTML页面<link>
.浏览器如何获取此样式表中的规则并将其应用于HTML?我不是在问如何让它更快,我想知道渲染本身是如何处理的.
它是否逐个应用每个规则,因为它会解析样式表并逐步呈现结果?或者,CSS文件的内容是否已完全下载,然后进行全面评估,然后立即应用于HTML?或者是其他东西?
我问这个上张贴一个答案较早之后关于影响渲染速度CSS规则的顺序问题,与样式被渲染的假设作为加载的样式,所以第一个规则会在最后的前应用,而不是一下子.我不确定我在哪里接受这个想法,这只是我一直想到的.
我在我的服务器上尝试了一个看起来像这样的演示:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<link rel="stylesheet" href="test.css" />
</head>
<body></body>
</html>
Run Code Online (Sandbox Code Playgroud)
test.css
内容:
html { background:green }
/* thousands of lines of irrelevant CSS to make the download slow */
html { background:red }
Run Code Online (Sandbox Code Playgroud)
在Firefox 5中进行测试,我希望首先看到绿色,然后变为红色.它没有发生.我尝试使用两个具有冲突规则的单独样式表并获得相同的结果.很多组合后,我得到了它工作的唯一途径是内嵌<style>
在块<head>
,与冲突的规则从未来<link>
的<body>
(身体本身完全除外链接标记为空).即使style
在<html>
标记上使用内联属性,然后加载此样式表也不会创建我期望的闪烁.
重绘是否受到CSS的任何影响,或者是在下载整个样式表后是否同时应用了最终输出,并且计算了最终输出应该是什么规则?CSS文件是否与HTML本身一起下载或阻止它(如脚本标签那样)?这实际上是如何工作的?
我不是在寻找优化技巧,我正在寻找有关该主题的权威参考资料,以便我将来可以引用它们.如果没有大量不相关的材料,就很难搜索这些信息.摘要:
@import
多个<link>
内联样式属性,<style>
头部块和不同渲染引擎等因素的影响?Mat*_*all 16
浏览器如何获取此样式表中的规则并将其应用于HTML?
通常,这是以流式方式完成的.浏览器将HTML标记作为流读取,并将其可以应用的规则应用到目前为止看到的元素.(显然这是一种简化.)
一个有趣的相关问答:使用CSS选择器从流式解析器(例如SAX流)收集HTML元素 (当我搜索我想到的文章时转移).
啊,这就是:为什么我们没有父选择器.
我们经常将我们的页面视为这些完整且完整的文档,其中包含元素和内容.但是,浏览器旨在处理像流一样的文档.他们开始从服务器接收文档,并可以在文档完全下载之前呈现文档.评估每个节点并在接收到视口时将其渲染到视口.
看一下示例文档的正文:
Run Code Online (Sandbox Code Playgroud)<body> <div id="content"> <div class="module intro"> <p>Lorem Ipsum</p> </div> <div class="module"> <p>Lorem Ipsum</p> <p>Lorem Ipsum</p> <p>Lorem Ipsum <span>Test</span></p> </div> </div> </body>
浏览器从顶部开始并看到一个
body
元素.此时,它认为它是空的.它尚未评估任何其他内容.浏览器将确定计算出的样式是什么,并将它们应用于元素.什么是字体,颜色,线高?在弄清楚之后,它将它绘制到屏幕上.接下来,它会看到
div
ID为的元素content
.同样,在这一点上,它认为它是空的.它尚未评估任何其他内容.浏览器计算出样式然后div
绘制.浏览器将确定是否需要重新绘制正文 - 元素是否变得更宽或更高?(我怀疑还有其他考虑因素,但宽度和高度变化是子元素对父母最常见的影响.)此过程将一直持续到文档结束.
CSS从右到左进行评估.
要确定CSS规则是否适用于特定元素,它将从规则的右侧开始,并以左侧的方式工作.
如果您
body div#content p { color: #003366; }
对每个元素都有一个规则- 当它被渲染到页面时 - 它首先会询问它是否是段落元素.如果是,它将在DOM上工作,并询问它是否div
具有内容ID.如果它找到它正在寻找的东西,它将继续向上移动到DOM,直到它到达body
.通过从右向左工作,浏览器可以确定规则是否适用于它尝试以更快的速度绘制到视口的此特定元素.要确定哪个规则的性能更高或更低,您需要确定需要评估多少个节点以确定是否可以将样式应用于元素.
那么为什么样式表内容不是逐步应用的(先绿色,然后是红色)?
我认为答案是外部样式表在下载时被解析,但在解析整个样式表之前不会应用.当然,在解析样式表时,浏览器会优化掉不必要的冗余CSS规则.
我现在没有任何证据证明这一点,但这个解释对我来说听起来很合理,并且同意你所看到的内容,包括外部和内联样式.
第一个也是最重要的一点是,在下载所有CSS之前,浏览器无法开始绘制页面.(请记住,W3C规范说CSS链接只允许在头部,所以当你开始链接到body标签中的样式表时,不同的浏览器会以不同的方式处理这种情况.)
现在,一个网页被视为一个流,并且当CSS元素被送入页面时,CSS规则被应用于HTML元素.引用下面链接的Google文章:
当浏览器解析HTML时,它构造一个内部文档树,表示要显示的所有元素.然后根据标准的CSS级联,继承和排序规则,将元素与各种样式表中指定的样式进行匹配.
所以现在解决你的问题:
它是否逐个应用每个规则,因为它会解析样式表并逐步呈现结果?或者,CSS文件的内容是否已完全下载,然后进行全面评估,然后立即应用于HTML?或者是其他东西?
下载所有CSS,然后开始从上到下绘制文档.
在Firefox 5中进行测试,我希望首先看到绿色,然后变为红色.它没有发生.我尝试使用两个具有冲突规则的单独样式表并获得相同的结果.
这是因为CSS首先全部下载,然后当它遇到你的元素时它只应用了红色样式,因为级联的工作方式.
经过多次组合之后,我得到它的唯一方法是使用内联
<style>
块<head>
,其中冲突规则来自<link>
于<body>
虽然我不能确切地说出为什么会发生这种情况,但我认为浏览器并没有在body标签中寻找CSS,开始绘画,遇到了身体CSS,然后重新绘制.
CSS会以任何方式影响重绘吗?
老实说,我更担心JS引起的重绘.但是如果你有一个非常大的DOM,那么构造你的CSS是有意义的,这样你就不会因为奇怪的定位而导致回流.@Matt给了你一些关于这个问题的好链接一些好的资源:
http://www.dayofjs.com/videos/22158462/web-browsers_alex-russel Alex Russell在36分钟内详细介绍了webkit如何解析CSS,回流和重绘如何工作以及触发它们的原因.
http://code.google.com/speed/page-speed/docs/rendering.html 这是关于如何优化CSS渲染的基础文章