0

0

关于网页渲染,前端们应该知道的一些事情_html/css_WEB-ITnose

php中文网

php中文网

发布时间:2016-06-21 08:46:57

|

1359人浏览过

|

来源于php中文网

原创

浏览器是如何渲染网页的?

我们从浏览器渲染一个页面的行为说起:

  • 从服务器端获取的HTML文档中构建出DOM树(文档对象模型);

  • 样式被加载和分析,构建CSSOM(CSS对象模型);

  • 以DOM和CSSOM为基础,文档树被构建,一系列对象被渲染(Webkit称每一个为‘renderer’或’render 对象(render object)‘,Gecko中称为‘frame’).渲染树反应了除不可见元素(

    , display:none)之外的DOM结构中一切可见元素,每一段字符串在渲染树中都被当做独立的渲染对象,每一个渲染对象都是其对应的DOM结构和计算所得样式的混合体,换句话说渲染树是DOM树的视觉表现;
  • 对于每一个渲染树元素,它的坐标都是通过计算获得的,这被称作排版(布局layout),浏览器通过文档流的方式(也就是一次就能完成所有元素的布局)(tables需要多于一次的布局);

  • 最终渲染树出现在浏览器窗口上,这个过程称为绘制(painting)。

当用户与一个页面交互或者脚本修改时,由于文档结构的变化,以上的一些操作步骤会重新执行。

重现绘制(Repaint)

当元素样式变化并不影响该元素在一个网页上的位置时( background-color, border-color, visibility),浏览器只会把新样式应用到该元素。

Reflow

当改变影响了 文档内容或结构或者元素的位置时,reflow发生(重新布局),这一般由以下因素触发:

  • DOM操作(添加,删除,更改,或者变更元素顺序);

  • 内容改变(包括表格区域内文本的变化)(所占位置大小变了);

  • 计算或者改变CSS属性(位置改变);

  • 添加或者删除样式表;

  • 改变类属性(class)(可能会改变位置);

  • 浏览器窗口操作(改变大小,滚动);

  • 伪类激活(可能改变位置)

怎么让浏览器充分利用渲染机制

浏览器会尽可能的限制被改变元素所在区域的重排重绘,比如说 display:fixed/absolute元素改变时只会影响它本身和它的子元素,而 display:static元素改变时会使其随后的元素都被重绘;(影响尽量少的元素)

立即学习前端免费学习笔记(深入)”;

另一个最大化性能的机制在于,当运行一系列JavaScript片段时,浏览器会缓存它们,然后一次运行。看下面的例子可以很好的理解:

var $body = $('body');$body.css('padding', '1px'); // reflow, repaint$body.css('color', 'red'); // repaint$body.css('margin', '2px'); // reflow, repaint// only 1 reflow and repaint will actually happen(由于缓存,只会重绘一次)

然而,就像上面已经提到的,调用一个元素的属性会触发强制性的reflow,当我们加上一行读元素属性的代码时就会发生;

var $body = $('body');$body.css('padding', '1px');$body.css('padding'); // reading a property, a forced reflow(强制发生)$body.css('color', 'red');$body.css('margin', '2px');//另外一次reflow

因此,会有两次reflow,因此应该组合来读元素属性已最大化性能 一个详细的例子;

Krea AI
Krea AI

多功能的一站式AI图像生成和编辑平台

下载
$(function() {  var $body = $('body');  $body  .on('click', '.block-1', function(e) {    // 1 reflow        $body.css('padding', '1px');    $body.css('color', 'red');    $body.css('margin', '2px');  })  .on('click', '.block-2', function(e) {    // 2 reflows        $body.css('padding', '1px');    $body.css('padding');    $body.css('color', 'red');    $body.css('margin', '2px');  })  .on('click', '.block-3', function(e) {    // 3 repaints        $body.css('color', 'red');    $body.css('color');    $body.css('color', 'yellow');    $body.css('background');    $body.css('color', 'blue');    $body.css('outline');  })  .on('click', '.block-4', function(e) {    // 1 repaint        $body.css('color', 'red');    $body.css('color', 'yellow');    $body.css('color', 'blue');    $body.css('color');    $body.css('background');    $body.css('outline');  })  .on('click', '.block-5', function(e) {    // 3 reflows        $body.css('padding', '1px');    $body[0].offsetHeight;    $body.css('padding', '2px');    $body[0].offsetTop;    $body.css('padding', '3px');    $body[0].offsetWidth;  })  .on('click', '.block-6', function(e) {    // 1 reflow        $body.css('padding', '1px');    $body.css('padding', '2px');    $body.css('padding', '3px');    $body[0].offsetHeight;    $body[0].offsetTop;    $body[0].offsetWidth;  });});

有些时候,可能你会需要一次强制性的reflow,例如:我们需要运用两次 margin-left到同一个对象,第一次无动画的设置到100px,然后通过动画过渡到50px, 实例;

过渡动画:

.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;}

过程代码:

// our element that has a "has-transition" class by defaultvar $targetElem = $('#targetElemId');// remove the transition class$targetElem.removeClass('has-transition');// change the property expecting the transition to be off, as the class is not there// anymore$targetElem.css('margin-left', 100);// put the transition class back$targetElem.addClass('has-transition');// change the property$targetElem.css('margin-left', 50);

上述代码并不按预期工作,因为改变被缓存并在最后执行了一次,这时候我们就需要一次强制性的执行了:

达到预期效果的代码

// remove the transition class$(this).removeClass('has-transition');// change the property$(this).css('margin-left', 100);// trigger a forced reflow, so that changes in a class/property get applied immediately$(this)[0].offsetHeight; // an example, other properties would work, too// put the transition class back$(this).addClass('has-transition');// change the property$(this).css('margin-left', 50);

现在达到预期效果了!

性能优化的建议

总结了一些有用的信息,本文有以下建议

  • 构建有效的HTML和CSS,不要忘记声明文档编码方式,样式表应该包含在

    标签内,脚本文件应该放在 标签的底部;
  • 简化并且充分利用CSS选择器(这一条被大多数使用CSS预处理器的开发者忽略),维护最少的层状结构,以下是各选择器的效率排行

    #id.classdiva+iul>li*input[type='text']a:hover
  • 应该引起注意的是,浏览器是从右向左读取选择器的,所以最右边的应该选择效率比较高的选择器 #id,.class;

div * {...} // bad.list li {...} // bad.list-item {...} // good#list .list-item {...} // good
  • 在脚本中,应该尽可能的减少DOM操作,如果对象和属性会被重用,就缓存它们。在最好离线元素(未被插入文档树)(offline)上进行操作,然后把它插入DOM结构中;

  • 如果使用jQuery,遵循[jQuery选择器基本原则( http://learn.jquery.com/performance/optimize-selectors/);

  • 修改元素的样式时,修改class属性是做好的方法,其位置越深,越好(also because this helps decouple logic from presentation);

  • 只使 display:fixed/absolute的元素具有动画;

  • 不适用复杂的 :hover动画也是一个好的实践(给

    添加 no-hover属性), 延展阅读;

延展阅读已获得更多信息:

  1. How browsers works;

  2. Rendering: repaint, reflow/relayout, restyle;

希望这边译文对您有用

原文链接

相关文章

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
C++ 高级模板编程与元编程
C++ 高级模板编程与元编程

本专题深入讲解 C++ 中的高级模板编程与元编程技术,涵盖模板特化、SFINAE、模板递归、类型萃取、编译时常量与计算、C++17 的折叠表达式与变长模板参数等。通过多个实际示例,帮助开发者掌握 如何利用 C++ 模板机制编写高效、可扩展的通用代码,并提升代码的灵活性与性能。

10

2026.01.23

php远程文件教程合集
php远程文件教程合集

本专题整合了php远程文件相关教程,阅读专题下面的文章了解更多详细内容。

29

2026.01.22

PHP后端开发相关内容汇总
PHP后端开发相关内容汇总

本专题整合了PHP后端开发相关内容,阅读专题下面的文章了解更多详细内容。

21

2026.01.22

php会话教程合集
php会话教程合集

本专题整合了php会话教程相关合集,阅读专题下面的文章了解更多详细内容。

21

2026.01.22

宝塔PHP8.4相关教程汇总
宝塔PHP8.4相关教程汇总

本专题整合了宝塔PHP8.4相关教程,阅读专题下面的文章了解更多详细内容。

13

2026.01.22

PHP特殊符号教程合集
PHP特殊符号教程合集

本专题整合了PHP特殊符号相关处理方法,阅读专题下面的文章了解更多详细内容。

11

2026.01.22

PHP探针相关教程合集
PHP探针相关教程合集

本专题整合了PHP探针相关教程,阅读专题下面的文章了解更多详细内容。

8

2026.01.22

菜鸟裹裹入口以及教程汇总
菜鸟裹裹入口以及教程汇总

本专题整合了菜鸟裹裹入口地址及教程分享,阅读专题下面的文章了解更多详细内容。

55

2026.01.22

Golang 性能分析与pprof调优实战
Golang 性能分析与pprof调优实战

本专题系统讲解 Golang 应用的性能分析与调优方法,重点覆盖 pprof 的使用方式,包括 CPU、内存、阻塞与 goroutine 分析,火焰图解读,常见性能瓶颈定位思路,以及在真实项目中进行针对性优化的实践技巧。通过案例讲解,帮助开发者掌握 用数据驱动的方式持续提升 Go 程序性能与稳定性。

9

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
go语言零基础开发内容管理系统
go语言零基础开发内容管理系统

共34课时 | 2.6万人学习

ASP教程
ASP教程

共36课时 | 22.8万人学习

传智播客AJAX视频教程
传智播客AJAX视频教程

共30课时 | 7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号