浏览器是如何渲染网页的

原文链接:What Every Frontend Developer Should Know About Webpage Rendering
转自:知乎-浏览器是如何渲染网页的
今天我们讨论的话题将专注于网页渲染以及它在Web开发中至关重要的作用。其实网上已经有许多谈论这个主题的文章了,但大多数文章提供的都是比较碎片化的信息,我需要查阅相当多的资料,才能完整地了解网页渲染。所以我决定写下这篇有一定综合性的文章。相信一方面能够帮助初学者了解网页渲染的原理,另一方面也能帮助有经验的同学细化巩固相关的知识结构。

不同的浏览器引擎运行起来会有些许差异,针对特定浏览器的具体内容会更加复杂。本文并不会涉及某个浏览器的底层原理,而是讨论一些通共的原则。

浏览器如何渲染网页

我们先来了解一下浏览器是如何对网页进行渲染的:

浏览器将从服务器获取的HTML文档构建成文档对象模型DOM(Document Object Model).
样式将被载入和解析,构成层叠样式表模型CSSOM(CSS Object Model).
在DOM和CSSOM之上,渲染树(rendering tree)将会被创建,代表一系列将被渲染的对象(这在Webkit内核中被称为renderer或者渲染对象render object,在Gecko内核中被称为框架frame)。渲染树映射除了不可见元素(例如或者含有display:none;的标签)外的所有DOM结构。每一段文本字符串都将划分在不同的渲染对象中,每一个渲染对象都包含了它相应的DOM对象以及计算后的样式。换句话讲,渲染树是DOM的直观表示。
渲染树的每个元素包含的内容都是计算过的,它被称之为布局layout.浏览器使用一种流式处理的方法,只需要一次pass绘制操作就可以布局所有的元素(tables需要多次pass绘制,pass表示像素处理和顶点处理)。
最后布局完成,渲染树将转化为屏幕上的实际内容,这一步被称为绘制painting.

重绘Repaint

当页面元素样式的改变不影响元素在文档流中的位置时(例如background-color, border-color,visibility),浏览器只会将新样式赋予元素并进行重绘操作。

回流Reflow

当改变影响文档内容或者结构,或者元素位置时,回流操作就会被触发,一般有以下几种情况:
- DOM操作(对元素的增删改,顺序变化等);

  • 内容变化,包括表单区域内的文本改变;
  • ** CSS属性的更改或重新计算;
    增删样式表内容;**
  • 修改class属性;
  • 浏览器窗口变化(滚动或缩放);
  • 伪类样式激活(:hover等)。

浏览器如何优化渲染

浏览器本身会尽可能地减少其重绘或回流的次数,只更改必要的元素。例如一个position设置为absolute/fixed的元素的更改只会影响其本身和其子元素,而static的元素变化则会影响其之后的所有页面元素。

另外一项优化的技术则是在JavaScript代码运行时,浏览器会缓存所有的变化,然后只通过一次pass绘制操作来应用这些更改。例如下面这段代码只会触发一次重绘和回流:

var $body = $('body');
$body.css('padding', '1px'); // 触发重绘与回流
$body.css('color', 'red'); // 触发重绘
$body.css('margin', '2px'); // 触发重绘与回流
// 最终只有一次重绘和回流被触发

然而,根据我们之前提到过的,获取某个元素的属性将会触发强制回流。比如我们在刚才的代码中加上一句读取元素属性的操作:

var $body = $('body');
$body.css('padding', '1px');
$body.css('padding'); // 此处触发强制回流
$body.css('color', 'red');
$body.css('margin', '2px');

结果就会有两次回流发生。因此,我们应该尽量合并读取元素属性的操作来优化性能。

当然也有我们不得不触发强制回流的情况。比如说对同一个元素的margin-left属性进行两次操作——开始的时候赋值100px的距离,之后为了实现动画效果,再加上transition属性将距离改变到50px.

我们先定义一个CSS类:

.has-transition {-webkit-transition: margin-left 1s ease-out;-moz-transition: margin-left 1s ease-out;-o-transition: margin-left 1s ease-out;transition: margin-left 1s ease-out;
}

之后再对页面元素进行操作:

// 我们的元素开始默认含有 "has-transition" 的class属性
var $targetElem = $('#targetElemId');// 移除默认的 "has-transition"
$targetElem.removeClass('has-transition');// 此处的属性改变没有动画效果
$targetElem.css('margin-left', 100);// 再加上原来的属性名
$targetElem.addClass('has-transition');// 这次改变有动画效果
$targetElem.css('margin-left', 50);

但事实上这段代码并不会像注释描述的那样运作,每条语句的操作将被缓存,只有结果会在页面上显示,所以我们就需要手动进行一次强制回流:

// 移除默认的 "has-transition"
$(this).removeClass('has-transition');// 此处的属性改变没有动画效果
$(this).css('margin-left', 100);// 触发强制回流,上述两条语句的效果会马上在页面中显示
$(this)[0].offsetHeight; // 只是举个例子,别的触发方法也可以// 再加上原来的属性名
$(this).addClass('has-transition');// 这次改变有动画效果
$(this).css('margin-left', 50);

优化渲染效率的几条最佳实践

根据我查阅的一些资料,总结出以下几条优化建议:

-合法地书写HTML和CSS,不要忘了文档编码类型。样式文件应当在 标签中,脚本文件在 结束前。
-简化并优化你的CSS选择器(有些人可能CSS预处理器用习惯了从来不关注这一点)。将嵌套层减少到最小。CSS选择器根据其优先级具有不同的运行效率(从快到慢):
1ID选择器: #id
2类选择器: .class
3标签选择器: div
4相邻选择器: a + i
5子元素选择器: ul > li
6通用选择器: *
7属性选择器: input[type=”text”]
8伪类选择器: a:hover

浏览器中CSS选择器是从右到左进行匹配的,这也是为什么越短的选择器运行越快的原因(别提通用选择器,它会遍历所有元素):

  • 在你的脚本代码中,尽量减少DOM操作。缓存所有的内容,包括属性和对象(如果他们需要被复用的话)。尽量将元素缓存到本地之后再进行操作,最后再添加到DOM当中。
  • 如果你使用jQuery进行DOM操作的话,最好遵循jQuery最佳实践。
  • 修改元素样式时,更改其class属性是性能最高的方法。你的选择器越有针对性越好(这同样也有助于分离页面样式和逻辑)。
  • 尽量只对 position 为 absolute/fixed 的元素设置动画。
  • 在页面滚动时禁用 :hover 样式效果:
.disable-hover {pointer-events: none;
}
var body = document.body,timer;window.addEventListener('scroll', function() {clearTimeout(timer);if(!body.classList.contains('disable-hover')) {body.classList.add('disable-hover')}timer = setTimeout(function(){body.classList.remove('disable-hover')},500);
}, false);

如果你想对此话题进行更深入的了解,可以查阅:
How browsers work[中文版]

【译】浏览器渲染:repaint,reflow/relayout,restyle

有任何好的意见或者是建议以及心得体会欢迎在评论区参与讨论。

浏览器是如何渲染网页的相关推荐

  1. 浏览器是怎样渲染网页的呢?

    我在掘金上重新整理了这篇文章----浏览器渲染网页过程 - 掘金,格式更加简介好看一些. 目录 Document Object Model (DOM) CSS Object Model (CSSOM) ...

  2. 双核浏览器选择内核渲染网页

    一.HTML的meta标签 <meta>元素可以提供页面的元信息.必要的属性为content content: 定义与 http-equiv 或 name 属性相关的元信息 可选属性有na ...

  3. 浏览器加载渲染网页过程解析-总结

    js的加载会阻塞此js文件下面的图片的加载,但不会阻塞其他js,css的加载 js的加载会阻塞浏览器的渲染,需要等待js加载执行完毕后才可以继续渲染 js的加载虽然是异步进行的,但是执行仍然会保持从上 ...

  4. 浏览器是如何渲染网页的《学如逆水行舟,不进则退》

    2019独角兽企业重金招聘Python工程师标准>>> 现在我们主要接触的主流浏览器有:IE, FireFox, Safari, Chrome,Opera; 你真的了解它们吗? 1. ...

  5. 游览器加载渲染网页过程分析

    游览器的工作机制,一句话概括起来就是,web游览器与web服务器之间通过http协议进行通信的过程,所以,c/s之间的协议就是http协议,游览器接受完毕开始渲染大致过程如下: http://blog ...

  6. 理解浏览器是如何加载及渲染网页的

    先上图,我们再慢慢解释,这图就是浏览器加载网页的一个过程 当我们在浏览器输入一个地址(比如:http://toadw.cn),那么点击回车后,浏览器是如何加载网页的呢? 加载过程 一开始浏览器是不知道 ...

  7. 《十》浏览器基础及渲染引擎解析一个网页的过程、JavaScript 引擎解析 JavaScript 代码的过程

    浏览器:是安装在电脑里面的一个软件,能够将页面内容渲染出来呈现给用户查看,并让用户与网页进行交互. 服务器其实就是性能比较高的计算机,这些计算机 24 小时不断电. 不关机. 开发者在本地开发出 HT ...

  8. 强制Edge浏览器以深色模式渲染网页

    问题简介 开发者常常需要长时间浏览网页,过亮的页面容易造成视觉疲劳.虽然最新的Windows版本已经支持全局的深色主题,但浏览器渲染网页时,依然会按照网页的默认底色进行页面渲染.这篇文章介绍如何强制E ...

  9. 6张图让你搞懂浏览器渲染网页过程

    我的想法:如果我要构建快速可靠的网站,需要真正了解浏览器渲染网页的每个步骤机制,这样就可以在开发过程中对每个步骤进行优化. 这篇文章是我在较高水平上对端到端过程的学习总结. 好了,废话不多说,我们开始 ...

  10. 浏览器tab关闭事件_翻译|揭示现代浏览器原理(2):网页访问 — Chrome官方

    原文:Inside look at modern web browser (part 2) 网页访问过程中发生了什么 这是揭秘浏览器原理系列的第二篇,在上一篇,我们讲解了浏览器如何利用不同的进程和线程 ...

最新文章

  1. SQL培训内容转之wantin6(收藏)
  2. 阿里云消息队列python_41. Python Queue 多进程的消息队列 PIPE
  3. angular基本知识学习笔记 - Component的基本概念
  4. 在OpenShift上托管的WildFly实例上进行Arquillian测试
  5. flink Datastream组装
  6. 1052. Linked List Sorting
  7. 如何选择行业,让选择大于努力
  8. MySQL数据库远程连接开启方法
  9. 0018-大数据售前的中年危机
  10. ceb2Pdf.exe实现ceb文件转pdf,内网离线安装wine(手动编译32位)实现在centos(linux)上运行window程序exe程序,解决wine : Z:\xxx EXE格式无效
  11. SpringBoot使用快递鸟进行电子面单的获取以及打印
  12. android soundpool 播放音效,Android使用SoundPool播放短音效
  13. 第十三章:(1)CompletableFuture异步回调
  14. 持安科技孙维伯:零信任 业务与安全的最优解
  15. vero visi 2021中文版
  16. 让lebel和radio/checkbox水平对齐
  17. php 正则匹配img标签中的自定义属性值
  18. Keil5/MDK结构体无法自动指示成员变量
  19. Redis实现信息已读未读红点状态提示功能
  20. 滴滴使用 HDFS EC 节约大量存储的实践

热门文章

  1. Java初学者作业——定义客户类(Customer),客户类的属性包括:姓名、年龄、电话、余额、账号和密码;方法包括:付款。
  2. SQL19 查找所有员工的last_name和first_name以及对应的
  3. Excel学习日记:L30-制作甘特图
  4. Python pandas DataFrame排序与去重操作
  5. 企查查等人物关系图谱、企业图谱等效果
  6. 联想集团大裁员:“公司不是家” 和 “柳传志的回应”(
  7. ARX中各种坐标系及Transfrom操作相关
  8. 0成本睡后收入!从0教你搭建外卖红包CPS小程序
  9. 手机html微信登录,添加手机APP微信登录支持,微信公众号单页应用网页授权登录支持...
  10. EXCEL 制作多簇并列的堆积柱形图