在写前端的时候,了解了一些浏览器兼容的问题,印象最深的还是圆角和渐变(感谢千年弦歌)。
浏览器最重要或者说核心的部分是“Rendering Engine”,我们一般称之为“浏览器内核”。 它负责对网页语法的解释(如HTML、JavaScript)并渲染(显示)网页。
相同的代码在不同的浏览器呈现出来的效果不一样,那么就很有可能是不同的浏览器内核导致的。
那么问题来了 ——
一、整理一下主流浏览器的内核:
Trident(windows)——IE
其他:世界之窗,360安全浏览器, 遨游2.0(3.0以上版本开始采用webkit内核),搜狗浏览器,腾讯TT
trident直译是三叉的(还是美国一个口香糖牌子,什么鬼跑偏了)
Gecko(跨平台)——FireFox 直译是壁虎,gecko是Netscape6开始采用的内核,后来的Mozilla FireFox (火狐浏览器) 也采用了该内核,Gecko的特点是代码完全公开,因此,其可开发程度很高,全世界的程序员都可以为其编写代码,增加功能。
因为这是个开源内核,因此受到许多人的青睐,Gecko内核的浏览器也很多,这也是Geckos内核虽然年轻但市场占有率能够迅速提高的重要原因。
Presto——Opera前内核==
presto直译是急板的,说变就变的。该内核在2003年的Opera7中首次被使用,该款引擎的特点就是渲染速度的优化达到了极致,也是之前公认网页浏览速度最快的浏览器内核,然而代价是牺牲了网页的兼容性。
Webkit——苹果的safari(win/mac/iphone/ipad) 、google的chrome、opera(2015转webkit)、塞班手机浏览器、Android手机默认的浏览器、搜狗浏览器、QQ浏览器
苹果公司自己的内核,也是苹果的Safari浏览器使用的内核。
其中基于webkit的chromium内核的有——搜狗浏览器、QQ浏览器、chrome、360、opera(这个内核现在才是最快的)
知乎上看到一句话:Chromium不是靠采用WebKit赢的,是靠它在WebKit基础上做出了自己的特色而赢的。
然而,现在国内很多浏览器都采用了双核,例如360极速/安全浏览器、猎豹浏览器、遨游浏览器、搜狗浏览器。
国产双核浏览器都有两个核,分别是IE兼容内核(也叫兼容模式)和基于Chromium开发的极速内核(也叫极速模式或高速模式)。
简单来说,基于Chromium内核的极速模式上网速度会更快,并且支持各种浏览器扩展插件(也就是添加各种你想要的功能),唯一的缺陷就是不支持国内某些不更新的网站(例如政府和部分银行的)。一般情况下使用极速模式来上网就对了,当发现网页显示不正常时,再手动切换到IE兼容模式就行。
一般切换方式:在地址栏上点一下“IE图标”或者“闪电图标”就能切换到另一个内核。
Web页面运行在各种各样的浏览器当中,浏览器载入、渲染页面的速度直接影响着用户体验简单地说,页面渲染就是浏览器将html代码根据CSS定义的规则显示在浏览器窗口中的这个过程。先来大致了解一下浏览器都是怎么干活的:
1. 用户输入网址(假设是个html页面,并且是第一次访问),浏览器向服务器发出请求,服务器返回html文件;
2. 浏览器开始载入html代码,发现<head>标签内有一个<link>标签引用外部CSS文件;
3. 浏览器又发出CSS文件的请求,服务器返回这个CSS文件;
4. 浏览器继续载入html中<body>部分的代码,并且CSS文件已经拿到手了,可以开始渲染页面了;
5. 浏览器在代码中发现一个<img>标签引用了一张图片,向服务器发出请求。此时浏览器不会等到图片下载完,而是继续渲染后面的代码;
6. 服务器返回图片文件,由于图片占用了一定面积,影响了后面段落的排布,因此浏览器需要回过头来重新渲染这部分代码;
7. 浏览器发现了一个包含一行Javascript代码的<script>标签,赶快运行它;
8. Javascript脚本执行了这条语句,它命令浏览器隐藏掉代码中的某个
![不同内核浏览器的差异以及浏览器渲染简介](https://i-blog.csdnimg.cn/blog_migrate/e429f5542a711c4f27908411a5746a96.jpeg)
![不同内核浏览器的差异以及浏览器渲染简介](https://i-blog.csdnimg.cn/blog_migrate/f879f49530ab117ee546d70426059316.jpeg)
reflow问题是可以优化的,我们可以尽量减少不必要的reflow。比如开头的例子中的<img>图片载入问题,这其实就是一个可以避免的reflow——给图片设置宽度和高度就可以了。这样浏览器就知道了图片的占位面积,在载入图片前就预留好了位置。
另外,有个和reflow看上去差不多的术语:repaint,中文叫重绘。 如果只是改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性,将只会引起浏览器repaint。repaint的速度明显快于 reflow(在IE下需要换一下说法,reflow要比repaint 更缓慢)
三、从浏览器的渲染原理讲CSS性能
平时我们几乎每天都在和浏览器打交道,写出来的页面很有可能在不同的浏览器下显示的不一样。苦逼的前端攻城师们为了兼容各个浏览器而不断地去测试和调试,还在脑子中记下各种遇到的BUG及解决方案,而我们好像并没有去主动地关注和了解下浏览器的工作原理。如果我们对此做一点了解,我想在项目过程中就可以根据它有效的避免一些问题以及对页面性能做出相应的改进。
我们来看一下加载页面时浏览器的具体工作流程:
1、解析HTML以重建DOM树(Parsing HTML to construct the DOM tree ):渲染引擎开始解析HTML文档,转换树中的标签到DOM节点,它被称为“内容树”。
2、构建渲染树(Render tree construction):解析CSS(包括外部CSS文件和样式元素),根据CSS选择器计算出节点的样式,创建另一个树 —- 渲染树。
3、布局渲染树(Layout of the render tree): 从根节点递归调用,计算每一个元素的大小、位置等,给每个节点所应该出现在屏幕上的精确坐标。
4、绘制渲染树(Painting the render tree) : 遍历渲染树,每个节点将使用UI后端层来绘制。
主要的流程就是:构建一个dom树,页面要显示的各元素都会创建到这个dom树当中,每当一个新元素加入到这个dom树当中,浏览器便会通过css引擎查遍css样式表,找到符合该元素的样式规则应用到这个元素上。
注意了:css引擎查找样式表,对每条规则都按从右到左的顺序去匹配。 看如下规则:
1
|
#nav
li {}
|
看起来很快,实际上很慢,尽管这让人有点费解#_#。我们中的大多数人,尤其是那些从左到右阅读的人,可能猜想浏览器也是执行从左到右匹配规则的,因此会推测这条规则的开销并不高。在脑海中,我们想象浏览器会像这样工作:找到唯一的ID为nav的元素,然后把这个样式应用到直系子元素的li元素上。我们知道有一个ID为nav的元素,并且它只有几个Li子元素,所以这个CSS选择符应该相当高效。
事实上,CSS选择符是从右到左进行匹配的。了解这方面的知识后,我们知道这个之前看似高效地规则实际开销相当高,浏览器必须遍历页面上每个li元素并确定其父元素的id是否为nav。
1
|
*{}
|
额,这种方法我刚写CSS的也写过,殊不知这种效率是差到极点的做法,因为*通配符将匹配所有元素,所以浏览器必须去遍历每一个元素,这样的计算次数可能是上万次!
1
|
ul#nav{} ul.nav{}
|
在页面中一个指定的ID只能对应一个元素,所以没有必要添加额外的限定符,而且这会使它更低效。同时也不要用具体的标签限定类选择符,而是要根据实际的情况对类名进行扩展。例如把ul.nav改成.main_nav更好。
1
|
ul li li li .nav_item{}
|
对于这样的选择器,之前也写过,最后自己也数不过来有多少后代选择器了,何不用一个类来关联最后的标签元素,如.extra_navitem,这样只需要匹配class为extra_navitem的元素,效率明显提升了
对此,在CSS书写过程中,总结出如下性能提升的方案:
- 避免使用通配规则 如 *{} 计算次数惊人!只对需要用到的元素进行选择
- 尽量少的去对标签进行选择,而是用class 如:#nav li{},可以为li加上nav_item的类名,如下选择.nav_item{}
- 不要去用标签限定ID或者类选择符 如:ul#nav,应该简化为#nav
- 尽量少的去使用后代选择器,降低选择器的权重值 后代选择器的开销是最高的,尽量将选择器的深度降到最低,最高不要超过三层,更多的使用类来关联每一个标签元素
- 考虑继承 了解哪些属性是可以通过继承而来的,然后避免对这些属性重复指定规则
选用高效的选择符,可以减少页面的渲染时间,从而有效的提升用户体验,你可以看一下CSS selectors Test,这个实验的重点是评估复杂选择符和简单选择符的开销。也许当你想让渲染速度最高效时,你可能会给每个独立的标签配置一个ID,然后用这些ID写样式。那的确会超级快,也超级荒唐!这样的结果是语义极差,后期的维护难到了极点。