如何通过浏览器应用CSS,并且重绘受它影响? [英] How is CSS applied by the browser, and are repaints affected by it?

查看:156
本文介绍了如何通过浏览器应用CSS,并且重绘受它影响?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有一个HTML页面,其中有一个样式表< link> 。浏览器如何处理此样式表中的规则并将其应用于HTML?我不是问如何使它更快,我想知道如何处理渲染本身。



它是一个一个应用每个规则解析样式表并逐步呈现结果?或者,CSS文件的内容是否已完全下载,然后完全评估,然后立即应用于HTML所有?还是别的什么?



我先在



从左到右。



要确定CSS规则是否适用于特定元素,它
从规则的右边开始,以左边的方式工作。 / p>

如果你有一个规则像 body div#content p {color:#003366; } 然后
为每个元素 - 当它被呈现到页面 - 它首先问如果
它是一个段落元素。如果是,它将工作在DOM和
问它是否是一个 div 与内容的ID。如果它找到它正在查找
,它将继续它的DOM直到它到达 body



通过从右到左工作,浏览器可以确定规则
是否适用于它试图绘制到
视口的特定元素。要确定哪个规则大致是
的性能,你需要弄清楚需要评估多少节点
来确定一个样式是否可以应用到一个元素。








那么,为什么样式表内容不会逐步应用(先绿色,然后是红色)?

的答案是,外部样式表会被解析,因为




已下载,但未应用,直到整个样式表都已解析。当然,在解析样式表时,浏览器会优化掉不必要和冗余的CSS规则。



我现在没有任何证据来支持它,对我来说是合理的,并且同意你看到的,包括外部和内联样式。


Let's say we have an HTML page with a single stylesheet <link>. How does the browser take the rules in this stylesheet and apply it to the HTML? I'm not asking about how to make it faster, I want to know how the rendering itself is handled.

Does it apply each rule one-by-one as it parses the stylesheet and render the result progressively? Or, are the CSS file's contents completely downloaded, then fully evaluated, and then applied to the HTML all at once? Or something else?

I ask this after posting an answer earlier on a question about CSS rule order affecting rendering speed, with the assumption that the styles were rendered as the stylesheet loaded, so the first rules would be applied before the last ones, and not all at once. I'm not sure where I picked up the idea, it's just something I have always thought.

I tried a demo on my server that looked like this:

<!DOCTYPE html>
<html>
<head>
   <title>Test</title>
   <link rel="stylesheet" href="test.css" />
</head>
<body></body>
</html>

test.css contents:

html { background:green }
/* thousands of lines of irrelevant CSS to make the download slow */
html { background:red }

Testing in Firefox 5, I expected to see green at first, then turn to red. It didn't happen. I tried with two separate stylesheets with conflicting rules and got the same results. After many combinations, the only way I got it to work was an inline <style> block in the <head>, with the conflicting rules coming from a <link> in the <body> (the body itself was completely empty except for the link tag). Even using an inline style attribute on the <html> tag, and then loading this stylesheet did not create the flicker that I expected.

Are repaints affected in any way by the CSS, or is the final output applied all at once after the entire stylesheet is downloaded and it's rules computed to what the final output should be? Do CSS files download in paralel with the HTML itself or block it (like script tags do)? How does this actually work?

I am not looking for optimization tips, I'm looking for authoritative references on the subject, so that I can cite them in the future. It's been very difficult to search for this information without turning up tons of unrelated material. Summary:

  • Is all CSS content downloaded before any of it is applied? (reference please)
  • How is this affected by things like @import, multiple <link>s, inline style attributes, <style> blocks in the head, and different rendering engines?
  • Does the download of CSS content block the downloading of the the HTML document itself?

解决方案

How does the browser take the rules in this stylesheet and apply it to the HTML?

Typically this is done in a streaming fashion. The browser reads the HTML tags as a stream, and applies what rules it can to the elements it has seen so far. (Obviously this is a simplification.)

An interesting related Q&A: Use CSS selectors to collect HTML elements from a streaming parser (e.g. SAX stream) (a diversion while I search for the article I have in mind).


Ah, here it is: Why we don't have a parent selector.

We often think of our pages as these full and complete documents full of elements and content. However, browsers are designed to handle documents like a stream. They begin to receive the document from the server and can render the document before it has completely downloaded. Each node is evaluated and rendered to the viewport as it is received.

Take a look at the body of an example document:

<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>

The browser starts at the top and sees a body element. At this point, it thinks it's empty. It hasn't evaluated anything else. The browser will determine what the computed styles are and apply them to the element. What is the font, the color, the line height? After it figures this out, it paints it to the screen.

Next, it sees a div element with an ID of content. Again, at this point, it thinks it's empty. It hasn't evaluated anything else. The browser figures out the styles and then the div gets painted. The browser will determine if it needs to repaint the body—did the element get wider or taller? (I suspect there are other considerations but width and height changes are the most common effects child elements have on their parents.)

This process continues on until it reaches the end of the document.

CSS gets evaluated from right to left.

To determine whether a CSS rule applies to a particular element, it starts from the right of the rule and works it's way left.

If you have a rule like body div#content p { color: #003366; } then for every element—as it gets rendered to the page—it'll first ask if it's a paragraph element. If it is, it'll work its way up the DOM and ask if it's a div with an ID of content. If it finds what it's looking for, it'll continue its way up the DOM until it reaches the body.

By working right to left, the browser can determine whether a rule applies to this particular element that it is trying to paint to the viewport much faster. To determine which rule is more or less performant, you need to figure out how many nodes need to be evaluated to determine whether a style can be applied to an element.


So why was the stylesheet content not applied progressively (green first, then red)?

I think the answer is that external stylesheets are parsed as they are downloaded, but not applied until the entire stylesheet has been parsed. Surely, in parsing a stylesheet, the browser optimizes away unnecessary and redundant CSS rules.

I don't have any proof to back that up right now, but that explanation sounds reasonable to me and agrees with what you're seeing, both with external and inline styles.

这篇关于如何通过浏览器应用CSS,并且重绘受它影响?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆