css(八)浏览器渲染

html-css024

css(八)浏览器渲染,第1张

写css最逃不开的应该是浏览器兼容问题了吧,因为css存在一些 未定义行为 ,各个浏览器都会按照自己的渲染规则来表现,就会存在表现不一致的情况,还有很多属性某些浏览器不支持,很多时候需要我们用更通用的方法来实现一些UI效果。本文重点来说说浏览器是如何把一个页面渲染出来的。

主要流程:

DOM生成、样式计算、布局、分层、图层绘制、栅格化、合成显示

下面主要讲css相关的几个步骤

我们书写的html最终都会被解析成一颗dom树,它来表达的dom结构能被浏览器所理解,那css做的就是赋予dom节点每个元素样式。当然,我们写的css也是不能直接被浏览器理解的,需要转化成styleSheets,我们在浏览器控制台输入document.styleSheets就能看到。

styleSheets要应用到各个元素上还需要两个步骤:

最后得出dom节点每个元素的具体样式。

得到dom树后,浏览器会遍历这棵树,把所有可见的节点加到布局树中,再进行布局计算,得到每个节点的坐标位置,保存在布局树中。

得到每个元素的具体位置后,还不能开始绘制页面,因为我们的页面并不是二维的,3D变换,z轴排序、页面滚动等效果都需要图层来实现。所以浏览器会为特定的节点生成专门的图层便于这些效果的实现。那什么样的节点会创建专门的图层呢,包括拥有层叠上下文属性的元素以及需要剪裁(clip)的地方,可以看一下 css(五)层叠

在浏览器开发者工具会有一个Layers标签,这里面可以直观地看到页面的分层情况

当改变了元素宽高或者几何位置的时候,就会触发 重排 ,需要走一遍完整的渲染过程,开销最大。

如果只是改变颜色,那么布局阶段就不需要执行,可以直接进入绘制阶段,所以叫 重绘 ,省去了布局和分层,效率会比重排要高一些。

而使用css的transform实现动画效果,则可以避开重绘和重排,只进行后续的合成操作,被称为 合成 ,能大大提升绘制效率。

Ps 合成操作实在非主线程(GPU进程)上执行的,不占用主线程资源

了解 HTML 和 CSS 的渲染原理从以下几方面入手:

html各种渲染都是从浏览器开始的,分为浏览器解析和浏览器渲染两大步骤

一、浏览器解析

1、浏览器通过请求的 URL 进行域名解析,向服务器发起请求,接收文件(HTML、CSS、JS、Images等等)。

2、HTML 文件加载后,开始构建 DOM Tree

3、CSS 样式文件加载后,开始解析和构建 CSS Rule Tree

4、Javascript 脚本文件加载后, 通过 DOM API 和 CSSOM API 来操作 DOM Tree 和 CSS Rule Tree

二、浏览器渲染

1、浏览器引擎通过 DOM Tree 和 CSS Rule Tree 构建 Rendering Tree

2、Rendering Tree 并不与 DOM Tree 对应,比如像 <head>标签内容或带有 display: none的元素节点并不包括在 Rendering Tree 中 。

3、通过 CSS Rule Tree 匹配 DOM Tree 进行定位坐标和大小,是否换行,以及 position、overflow、z-index 等等属性,这个过程称为 Flow 或 Layout 。

4、最终通过调用Native GUI 的 API 绘制网页画面的过程称为 Paint 。

渲染原理示意图:

1、十六进制的颜色值对位数与大小写

编写十六进制颜色值时你可能会用小写字母或省略成3位数,关于这写法没找到确实的数据证明对浏览器的渲染效率是否有影响,但十六进制的颜色值默认标准是大写及6位数标注。在未知情况下不希望冒险而降低了渲染的效率。

* 不赞成 - color:#f3a

* 建议用 - color:#FF33AA

2、display与visibility的差异

他们用于设置或检索是否显示对象。display隐藏对象不保留物理空间,visibility为隐藏对象保留占据的物理空间。当浏览器渲染被占据的物理空间时,会有所消耗资源。

* 不赞成 - visibility:hidden

* 建议用 - display:none

3、border:none与border:0的区别

和display与visibility的关系类似,分别不保留与保留空间。更多的是border:0尽管可以隐藏掉边框,但它会为你保留border-color/border-style的使用权。

* 不赞成 - border:0

* 建议用 - border:none

4、不宜用过小的背景图片平铺

一张宽高1px的背景图片,虽然文件体积非常之小,但渲染宽高500px的板块需要重复平铺2500次。提高背景图片渲染效率跟图片尺寸及体积有关,最大的图片文件体积保持约70KB。

* 不赞成 - 宽高8px以下的平铺背景图片

* 建议用 - 衡量适中体积及尺寸的背景图片

5、慎用IE滤镜

IE的滤镜除了比较消耗资源外也有兼容性问题。当中有让PNG透明的滤镜,可采用GIF或JPG似透非透的办法来避免使用此滤镜。建议只在IE6应用GIF透明,因为IE7以上已经支持了PNG透明。

* 不赞成,滥用IE滤镜因为消耗资源外也有兼容性问题。

* 建议用,最好选择其它方法能避免使用滤镜。

6、*{ margin:0padding:0}避免浏览器样式差异

*号通配符把所有标签都初始化一遍,浏览器的渲染消耗一定的资源。有部分在标签在不同浏览器上几乎无差异,或是某些已经不推荐使用的标签(因为你不会去用它),它们不需通配符要重新初始化一遍这样做能节省一点资源。

* 不赞成,使用*号通配符

* 不赞成,div span button b table等标签纳入通配符控制内外填充样式

* 建议用,有选择性地使用通配符控制内外填充样式。

7、不要添加额外的标签来描述class或id

如果你有一个选择器是以id作为关键选择符,请不要添加多余标签名上去。因为ID是唯一的,你不要为了一个不存在的理由而降低了匹配的效率。

* 不赞成 - button#backButton { }

* 不赞成 - .menu-left #newMenuIcon { }

* 建议用 - #backButton { }

* 建议用 - #newMenuIcon { }

8、尽量选择最特殊的类来存放选择器

降低系统效率的一个最大原因是我们在标签类中用了过多的选择符。通过添加 class 到元素,我们可以将类别进行再细分为 class 类,这样就不用为了一个标签浪费时间去匹配过多的选择符了。

* 不赞成 - treeitem[mailfolder="true"] >treerow >treecell { }

* 建议用 - .treecell-mailfolder { }

9、避免子孙选择符

子孙选择符是CSS中最耗资源的选择符。他真的是非常的耗资源,尤其是在选择器使用标签类或通用类的时候。很多情况中,我们真正想要的是子选择符。除非有明确说明,在 UI CSS 中是严禁使用子孙选择符的。

* 不赞成 - treehead treerow treecell { }

* 好一点,但还是不行(参照下一条) - treehead >treerow >treecell { }

10、标签类中不要包含子选择符

不要在标签类中使用子选择符。否则,每次元素的出现,都会额外地增加匹配时间。(特别是当选择器似乎多半会被匹配的情况下)

* 不赞成 - treehead >treerow >treecell { }

* 建议用 - .treecell-header { }

11、留意所有子选择符的使用

小心地使用子选择符。如果你能想出一个的不使用他的方法,那么就不要使用。特别是在 RDF 树和菜单会频繁地使用子选择符,像这样。

* 不赞成 - treeitem[IsImapServer="true"] >treerow > .tree-folderpane-icon { }

请记住 RDF 的属性是可以在模板中被复制的!利用这一点,我们可以复制那些想基于该属性改变的子 XUL 元素上的 RDF 属性。

* 建议用 - .tree-folderpane-icon[IsImapServer="true"] { }

1、十六进制的颜色值对位数与大小写

编写十六进制颜色值时你可能会用小写字母或省略成3位数,关于这写法没找到确实的数据证明对浏览器的渲染效率是否有影响,但十六进制的颜色值默认标准是大写及6位数标注。在未知情况下不希望冒险而降低了渲染的效率。

* 不赞成 - color:#f3a

* 建议用 - color:#FF33AA

2、display与visibility的差异

他们用于设置或检索是否显示对象。display隐藏对象不保留物理空间,visibility为隐藏对象保留占据的物理空间。当浏览器渲染被占据的物理空间时,会有所消耗资源。

* 不赞成 - visibility:hidden

* 建议用 - display:none

3、border:none与border:0的区别

和display与visibility的关系类似,分别不保留与保留空间。更多的是border:0尽管可以隐藏掉边框,但它会为你保留border-color/border-style的使用权。

* 不赞成 - border:0

* 建议用 - border:none

4、不宜用过小的背景图片平铺

一张宽高1px的背景图片,虽然文件体积非常之小,但渲染宽高500px的板块需要重复平铺2500次。提高背景图片渲染效率跟图片尺寸及体积有关,最大的图片文件体积保持约70KB。

* 不赞成 - 宽高8px以下的平铺背景图片

* 建议用 - 衡量适中体积及尺寸的背景图片

5、慎用IE滤镜

IE的滤镜除了比较消耗资源外也有兼容性问题。当中有让PNG透明的滤镜,可采用GIF或JPG似透非透的办法来避免使用此滤镜。建议只在IE6应用GIF透明,因为IE7以上已经支持了PNG透明。

* 不赞成,滥用IE滤镜因为消耗资源外也有兼容性问题。

* 建议用,最好选择其它方法能避免使用滤镜。

6、*{ margin:0padding:0}避免浏览器样式差异

*号通配符把所有标签都初始化一遍,浏览器的渲染消耗一定的资源。有部分在标签在不同浏览器上几乎无差异,或是某些已经不推荐使用的标签(因为你不会去用它),它们不需通配符要重新初始化一遍这样做能节省一点资源。

* 不赞成,使用*号通配符

* 不赞成,div span button b table等标签纳入通配符控制内外填充样式

* 建议用,有选择性地使用通配符控制内外填充样式。

7、不要添加额外的标签来描述class或id

如果你有一个选择器是以id作为关键选择符,请不要添加多余标签名上去。因为ID是唯一的,你不要为了一个不存在的理由而降低了匹配的效率。

* 不赞成 - button#backButton { }

* 不赞成 - .menu-left #newMenuIcon { }

* 建议用 - #backButton { }

* 建议用 - #newMenuIcon { }

8、尽量选择最特殊的类来存放选择器

降低系统效率的一个最大原因是我们在标签类中用了过多的选择符。通过添加 class 到元素,我们可以将类别进行再细分为 class 类,这样就不用为了一个标签浪费时间去匹配过多的选择符了。

* 不赞成 - treeitem[mailfolder="true"] >treerow >treecell { }

* 建议用 - .treecell-mailfolder { }

9、避免子孙选择符

子孙选择符是CSS中最耗资源的选择符。他真的是非常的耗资源,尤其是在选择器使用标签类或通用类的时候。很多情况中,我们真正想要的是子选择符。除非有明确说明,在 UI CSS 中是严禁使用子孙选择符的。

* 不赞成 - treehead treerow treecell { }

* 好一点,但还是不行(参照下一条) - treehead >treerow >treecell { }

10、标签类中不要包含子选择符

不要在标签类中使用子选择符。否则,每次元素的出现,都会额外地增加匹配时间。(特别是当选择器似乎多半会被匹配的情况下)

* 不赞成 - treehead >treerow >treecell { }

* 建议用 - .treecell-header { }

11、留意所有子选择符的使用

小心地使用子选择符。如果你能想出一个的不使用他的方法,那么就不要使用。特别是在 RDF 树和菜单会频繁地使用子选择符,像这样。

* 不赞成 - treeitem[IsImapServer="true"] >treerow > .tree-folderpane-icon { }

请记住 RDF 的属性是可以在模板中被复制的!利用这一点,我们可以复制那些想基于该属性改变的子 XUL 元素上的 RDF 属性。

* 建议用 - .tree-folderpane-icon[IsImapServer="true"] { } 1、十六进制的颜色值对位数与大小写

编写十六进制颜色值时你可能会用小写字母或省略成3位数,关于这写法没找到确实的数据证明对浏览器的渲染效率是否有影响,但十六进制的颜色值默认标准是大写及6位数标注。在未知情况下不希望冒险而降低了渲染的效率。

* 不赞成 - color:#f3a

* 建议用 - color:#FF33AA

2、display与visibility的差异

他们用于设置或检索是否显示对象。display隐藏对象不保留物理空间,visibility为隐藏对象保留占据的物理空间。当浏览器渲染被占据的物理空间时,会有所消耗资源。

* 不赞成 - visibility:hidden

* 建议用 - display:none

3、border:none与border:0的区别

和display与visibility的关系类似,分别不保留与保留空间。更多的是border:0尽管可以隐藏掉边框,但它会为你保留border-color/border-style的使用权。

* 不赞成 - border:0

* 建议用 - border:none

4、不宜用过小的背景图片平铺

一张宽高1px的背景图片,虽然文件体积非常之小,但渲染宽高500px的板块需要重复平铺2500次。提高背景图片渲染效率跟图片尺寸及体积有关,最大的图片文件体积保持约70KB。

* 不赞成 - 宽高8px以下的平铺背景图片

* 建议用 - 衡量适中体积及尺寸的背景图片

5、慎用IE滤镜

IE的滤镜除了比较消耗资源外也有兼容性问题。当中有让PNG透明的滤镜,可采用GIF或JPG似透非透的办法来避免使用此滤镜。建议只在IE6应用GIF透明,因为IE7以上已经支持了PNG透明。

* 不赞成,滥用IE滤镜因为消耗资源外也有兼容性问题。

* 建议用,最好选择其它方法能避免使用滤镜。

6、*{ margin:0padding:0}避免浏览器样式差异

*号通配符把所有标签都初始化一遍,浏览器的渲染消耗一定的资源。有部分在标签在不同浏览器上几乎无差异,或是某些已经不推荐使用的标签(因为你不会去用它),它们不需通配符要重新初始化一遍这样做能节省一点资源。

* 不赞成,使用*号通配符

* 不赞成,div span button b table等标签纳入通配符控制内外填充样式

* 建议用,有选择性地使用通配符控制内外填充样式。

7、不要添加额外的标签来描述class或id

如果你有一个选择器是以id作为关键选择符,请不要添加多余标签名上去。因为ID是唯一的,你不要为了一个不存在的理由而降低了匹配的效率。

* 不赞成 - button#backButton { }

* 不赞成 - .menu-left #newMenuIcon { }

* 建议用 - #backButton { }

* 建议用 - #newMenuIcon { }

8、尽量选择最特殊的类来存放选择器

降低系统效率的一个最大原因是我们在标签类中用了过多的选择符。通过添加 class 到元素,我们可以将类别进行再细分为 class 类,这样就不用为了一个标签浪费时间去匹配过多的选择符了。

* 不赞成 - treeitem[mailfolder="true"] >treerow >treecell { }

* 建议用 - .treecell-mailfolder { }

9、避免子孙选择符

子孙选择符是CSS中最耗资源的选择符。他真的是非常的耗资源,尤其是在选择器使用标签类或通用类的时候。很多情况中,我们真正想要的是子选择符。除非有明确说明,在 UI CSS 中是严禁使用子孙选择符的。

* 不赞成 - treehead treerow treecell { }

* 好一点,但还是不行(参照下一条) - treehead >treerow >treecell { }

10、标签类中不要包含子选择符

不要在标签类中使用子选择符。否则,每次元素的出现,都会额外地增加匹配时间。(特别是当选择器似乎多半会被匹配的情况下)

* 不赞成 - treehead >treerow >treecell { }

* 建议用 - .treecell-header { }

11、留意所有子选择符的使用

小心地使用子选择符。如果你能想出一个的不使用他的方法,那么就不要使用。特别是在 RDF 树和菜单会频繁地使用子选择符,像这样。

* 不赞成 - treeitem[IsImapServer="true"] >treerow > .tree-folderpane-icon { }

请记住 RDF 的属性是可以在模板中被复制的!利用这一点,我们可以复制那些想基于该属性改变的子 XUL 元素上的 RDF 属性。

* 建议用 - .tree-folderpane-icon[IsImapServer="true"] { }