Kampfer的记事本

新blog:www.kampfer-lw.com

导航

浏览器渲染优化守则(译文)

Posted on 2010-12-20 20:46  Kamfper  阅读(647)  评论(0编辑  收藏  举报

引言

网页资源被下载到客户端后,浏览器还需要对HTML,CSS,JavaScript等代码进行下载,解释,渲染等操作。利用浏览器的一些特性来组织你的代码和页面可以提高客户端的性能。

目录

使用高效的CSS选择器

不要使用CSS expressions

将CSS放在页面的head标签里

指定图片的尺寸

及早的指定字符集

使用高效的CSS选择器

概述

避免使用会匹配大量元素的Key Selectors,这样可以提高页面的渲染速度。

详情

在浏览器解析HTML的时候,它会构建一个内部的文档树,树中的每一个节点代表了将会被显示的元素。然后浏览器把元素和相应的样式关联起来,这个过程遵循CSS级联,继承以及次序规则。使用Mozilla内核的浏览器(其他类型的浏览器也可能类似)CSS引擎通过搜索CSS样式规则为每个元素寻找一个匹配样式。CSS引擎从右至左的识别CSS规则,它从最右端的key selector开始遍历规则内的每一个选择器直到找到一个匹配或者失败丢弃规则。

在这样的系统中,CSS引擎需要识别的CSS规则越少,性能越高。当然,删除无用的CSS也是提高渲染性能的步骤之一。总之,对于包含大量元素或CSS规则的页面优化CSS规则可以提高性能。优化CSS规则的关键是尽可能具体的定义CSS规则,避免不必要和冗余的定义。

下面的规则被认为是效率低下的:

含有后代选择器的规则

例如:

将全局选择器作为key selector的规则

  1. body * {...}  
  2. .hide-scrollbars * {...}  

将标签选择器作为key selector的规则

  1. ul li a {...}  
  2. #footer h3 {...}  
  3. * html #atticPromo ul li a {...}  

后代选择器效率低下是因为对于每一个被匹配的元素,浏览器必须遍历文档树,识别每一个父元素直到找到一个匹配或到达根元素。key selector越不具体,需要识别的节点就越多!

含有子选择器(和adjacent selectors)的规则

例如:

将全局选择器作为key selector的规则

  1. body > * {...}  
  2. .hide-scrollbars > * {...}  

将标签选择器作为key selector的规则

  1. ul > li > a {...}  
  2. #footer > h3 {...}  

子选择器(adjacent selectors)效率低下是因为对于每一个匹配的元素,浏览器必须识别另一个节点元素,这样规则中的每个子选择器都要花费两倍的资源,这明显是低效的。需要再次强调的是key selector越不具体,需要识别的节点就越多!但是相比后代选择器,子选择器还是有可取之处的。

包含ID选择器的规则

例如:

  1. ul#top_blue_nav {...}  
  2. form#UserLogin {...}  

ID选择器是唯一的。那么再在其中添加其他的选择器只会增加不必要的信息,浪费浏览器资源。

为非链接元素添加:hover伪类选择器的规则

例如:

  1. h3:hover {...}  
  2. .foo:hover {...}  
  3. #foo:hover {...}  
  4. div.faa :hover {...}  

在某些情况下,IE7和IE8中的非链接元素被添加:hover伪类虚选择器后效率也很低。如果我们没有定义严格版本的DTD,那么IE7和IE8将不会识别非链接元素上的:hover伪类;当我们定义了严格版本的DTD,那么在IE8和IE7下,非链接元素上的:hover将会引起性能方面的问题。

关于IE7和IE8下的:hover问题可以查看这:http://connect.microsoft.com/IE/feedback/ViewFeedback.aspx?FeedbackID=391387

建议

1.避免使用全局选择器

2.允许元素从父元素继承样式,或者使用类选择器为多个元素声明样式

3.尽可能具体的声明你的CSS规则

4.用ID选择器和类选择器代替标签选择器

5.删除多余的搭配

下面的搭配是冗余的:

  • 和ID选择器搭配在一起的类选择器和标签选择器
  • 和类选择器搭配在一起的标签选择器(每个类选择器只用在一个标签上是一个好方法!)

6.避免使用父选择器,尤其是冗余的父选择器

例如:规则“body ul li a {…}”定义了一个多余的body选择器,因为所有的元素都是body的后代。

7.用类选择器代替后代选择器,如果你必须使用后代选择器的话可以使用子选择器来代替。

8.不要在IE浏览器中为非链接元素定义:hover,你可以使用JavaScript来代替。

更多

完整的CSS说明:Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification

Mozilla高效CSS规则的说明:Writing Efficient CSS for Use in the Mozilla UI

避免使用CSS Expressions

概述

CSS Expressions会降低浏览器的渲染性能。使用替代品代替它们可以提高IE用户的浏览器渲染性能。

注意:本节内容只针对IE5到IE7,他们支持CSS Expressions,而IE8以后和其他浏览器一样不再支持CSS Expression。

详情

IE5引入了CSS表达式,或者称作“动态属性”。这是一种动态的改变文档属性以响应各种事件的手段。CSS Expressions将JavaScript当做CSS属性的值嵌入CSS声明当中。在大多数情况下,CSS expressions被用作以下目的:

模拟其他浏览器支持而IE不支持的CSS属性

为动态样式和高级事件处理提供一种小巧方便的途径,而不需要书写完整的JavaScript脚本

不幸的是,使用CSS expressions带来的性能上的“惩罚”是相当严重的。任何时候一旦有事件(任何事件)被触发,浏览器将重新计算CSS expressions。IE8不再支持CSS expressions是CSS expressions糟糕性能的另一个原因。如果你在你的页面中使用了CSS expressions,那么你将不得不删除它们,并使用其他方法来实现相同的功能。

建议

1.使用标准的CSS属性

IE8完全兼容CSS标准(W3C?)。在兼容模式下,IE8依然支持CSS expressions,但是在标准模式下不支持。如果你不需要对旧版本的IE浏览器保持向后的兼容性,你应该将使用CSS expressions的地方转换成标准的CSS。在CSS Attributes Index这里你可以找到IE各个版本支持的CSS属性的清单。如果你需要支持旧版本的IE,那么你可以使用JavaScript来实现模拟它们不支持的CSS属性。

2.使用JavaScript脚本

如果你使用CSS expressions来实现动态的样式,那么将它们改写成纯JavaScript脚本是十分有意义的:我们既可以改善IE的性能,同时在其他浏览器中也实现了相同的功能。

将CSS放在页面的head标签内

概述

将内联样式和link元素从<body>内移到<haed>里,这样可以提高渲染性能。

详情

在HTML文档的<body>中定义外部样式表和内联样式可能对浏览器的渲染性能产生不利影响。当所有外部样式被下载完毕后浏览器才开始渲染页面。内联样式(用<style>标记指定的)可能导致页面内容重载或者是漂移。因此,把外部样式表和内联样式块放在页面的<head>中是很重要的。通过确保样式表首先被下载和解析,可以让浏览器逐步渲染页面。

建议

1.HTML 4.01规范(第12.3节)规定,始终把使用<link>标签的外部样式表放在<head>部分里。不要使用@import。还要确保您指定的样式有正确的顺序

2.把<style>区块放在<head>部分里。

指定图片的尺寸

概述

为页面中所有图片指定宽度和高度可以消除不必要的重载和重绘,使页面渲染速度更快。

详情

当浏览器勾画页面时,它可以先暂时跳过那些可以替代的元素比如:图片。一旦向浏览器提供了可替代元素比如图片的尺寸,它甚至可以在图片下载完成之前开始渲染页面,将不可替代的元素包装在图片的周围。如果没有指定的图片尺寸,或者如果指定的尺寸不符合图片的实际尺寸,一旦图片下载完,浏览器将需要重载和重绘。为了防止重载,请在HTML的<img>标签中或在CSS中为所有图片指定宽度和高度。

建议

1.指定与图片本身相一致的尺寸

不要使用非图片原始尺寸来缩放图片。如果一个图片文件实际上的大小是60×60像素,不要在HTML或CSS里设置尺寸为30×30像素。如果图片需要较小的尺寸,可以在图像编辑软件中,设置成需要的的尺寸(详见优化图像。)

2.一定要指定图片或它的块级父元素的尺寸

一定要设置<img>元素本身,或它的块级父元素的尺寸。如果父元素不是块级元素,尺寸将被忽略。不要在一个非最近父元素的祖先元素上设置尺寸。

更多

本节“reflow”一词我翻译成了重载,就是浏览器为了重新渲染部分或整个页面,重新计算页面元素位置和几何结构的进程。

及早的指定字符集

概述

为你的HTML文档及早的指定字符集可以使得浏览器直接开始运行脚本

详情

HTML文档以一组绑定了字符编码信息的字节序列的形式在互联网上传输。在与文档一起传输的HTTP响应头或文档本身的HTML标记中定义了字符编码信息。浏览器通过字符编码信息将字节流转换为呈现在屏幕上的字符。不知道如何构造页面的字符浏览器就无法正确的渲染页面,所以大多数浏览器在运行JavaScript脚本或绘制页面时,会在输入中搜索字符编码信息同时缓冲一些字节(一个值得注意的例外是IE6/7/8)。

一旦浏览器缓冲足够的字节就会开始渲染页面。如果浏览器遇到一个与默认字符编码信息不匹配的字符编码定义,那么他将重新解析输入并重绘页面。有时,如果这个不匹配影响了外部资源的URLs浏览器甚至会重新请求资源。

为了避免这样的延误,你应该尽可能早的为大于1KB的HTML文档定义字符编码。

建议

1.HTTP响应头较之元标记参数更好

有几种为HTML文档指定字符集的方式:

服务器端:为类型为text/html的文档的Content-Type头的charset参数指定正确的字符编码,例如:Content-Type: text/html; charset=UTF-8。

客户端:在HTML中包含具有http-equiv=”content”属性的meta标签,并指定charset参数。例如:<meta http-equiv="Content-Type" content="text/html;charset=utf-8">

如果可能,在服务器指端指定HTTP头的字符集。如果在HTTP头中字符集已经被指定,那么部分浏览器(比如火狐)将会减少运行JavaScript前的缓冲时间。因为它们不再检查HTML文档中的<meta>。

2.在head的最前端指定<meta>

如果你无法控制服务器,你就需要在用meta设置字符集,并且保证<meta>在head的最前端。浏览器在文档的前1024bytes内搜索charset参数,从而避免性能的降低。charset参数应该尽可能早的被定义!

3.一定要定义content type

浏览器只有在确定待处理文档的content type后才能开始检查字符集。如果在HTTP头和<meta>中没有指定字符集,浏览器将会试图通过各种算法“嗅探”content type。这个过程将指定额外的延迟。而且这可能引起安全方面的问题。处于安全和性能两方面的考虑,你应该为所有资源指定content type。

4.确保指定正确的字符编码

在HTTP头或<meta>中指定的字符集必须和你用来组织HTML的字符编码相同。如果你在HTTP头和<meta>中都指定了字符集,那么保证他们是一致的。如果浏览器发现错误或不匹配的编码,他将错误的渲染页面和/或导致额外的重绘页面的延迟。

更多

英语原文

Optimize browser rendering

后记

这篇译文花费了我几天的时间,本人水平经验都十分有限,所以本文肯定会有不妥甚至是错误的地方,热烈欢迎留言指正或建议。另外在最后将要完成这篇译文的时候我在网上找到另一篇此文的翻译,不过不全,如果我的文章不如你的法眼,可以看这里:http://www.99css.com/?p=275


原创文章,转载请注明来自Kampfer