CSS面试题-回流与重绘 | “朝闻道”知识分享大赛

小年华°Moon 2023-11-17 08:23:57

这是我参加朝闻道知识分享大赛的第18篇文章。

注:CSS面试题分享板块的内容均为常见的前端面试中会涉及的知识点。
       具体的问题内容大同小异,大家遇到时具体问题具体分析即可。

前言:在我们对页面的元素进行修改时,常常会触发回流和重绘。少量的回流会重绘是不可避免的,但是我们需要注意我们的一些循环操作会导致大量的回流和重绘,将会影响浏览器的性能。本文介绍了页面渲染的流程以及回流和重绘的触发机制。了解这些机制,并学会使用一些常见的方法去减少回流和重绘,可以让我们的网页具有更好的性能。

目录

1. 概念

2. 如何触发

2.1 回流

2.2 重绘

3. 如何优化


1. 概念

在HTML中,每个元素都可以理解为一个盒子,在浏览器解析元素时,就会涉及到回流与重绘。

  • 回流:计算盒子的几何信息(大小和位置)。

  • 重绘:根据每个盒子的特性进行绘制。

浏览器渲染页面的具体流程:

  • 解析HTM和CSS,生成DOM树、CSSOM树

  • DOM树、CSSOM树结合,生成Render树

  • Layout(回流):根据Render树,回流得到节点的位置和大小

  • Painting(重绘):根据Render树和回流得到的节点的几何信息绘制具体的节点的绝对像素

  • Display(显示):把重绘获得的绝对像素发送到GPU,在页面上进行展示

综上,在页面最开始加载的过程中,回流和重绘是不可避免的会触发一次的。

  • 当我们修改元素的几何信息时,就会触发回流与重绘;

  • 当我们修改元素的特征信息时,只会触发重绘。

2. 如何触发

2.1 回流

我们前面提到,在几何信息被修改时,会触发回流,具体有以下几种行为:

  • 页面第一次渲染

  • 可见的DOM元素被删除

  • 元素的内容发生了变化

  • 元素的大小、位置发生了变化(包括边距、边框)

  • 浏览器的窗口尺寸发生了变化(回流根据视口大小计算元素的几何信息)

特殊的,在使用getComputedStyle方法或offset/scroll/client等属性时,由于这些方法/属性需要即使获取页面的几何信息,此时浏览器也会发生回流为我们获取这些值。

2.2 重绘

所有会触发回流的,一定会触发重绘。以下是会单独引起重绘的行为:

  • 修改颜色

  • 修改阴影

  • 修改文本方向

3. 如何优化

我们常用的优化方式如下:

  • 修改多个样式时,使用修改元素类名的方式,避免在js中直接修改样式

  • 插入多个节点时,使用DocumentFragment一次性插入多个创建好的节点

  • 避免使用table布局,因为table中每个元素的变动都会导致整个table的重新计算

  • 给复杂的动画设置position: fixed/absolute,让元素脱离文档流,减少对其他元素的影响

  • 由于CSS3的硬件加速,我们可以多使用transformopacityfilters,这些动画不会引起回流和重绘。

示例1:

优化前:每次单独操作都会触发一次渲染树的更改(新版本的浏览器中已优化)

const container = document.getElementById("container")
container.style.width = "100px"
container.style.height = "200px"
container.style.border = "10px solid red"
container.style.color = "red"

优化方法一:添加类名,一次性添加所有属性

<style>
  .basic_style {
    width: 100px;
    height: 200px;
    border: 10px solid red;
    color: red;
  }
</style>
<script>
  const container = document.getElementById("container")
  container.classList.add("basic_style")
</script>

优化方法二:离线操作,用display: none;去除元素后再进行操作

let container = document.getElementById('container')
container.style.display = 'none'
container.style.width = '100px'
container.style.height = '200px'
container.style.border = '10px solid red'
container.style.color = 'red'
container.style.display = 'block'

示例2:

优化前:在循环中多次获取offset属性,且多次触发渲染树渲染,会导致页面多次计算,发生多次回流。

const el = document.getElementById("el")
for (let i = 0; i < 10; i++) {
  el.style.top = el.offsetTop + 10 + "px"
  el.style.left = el.offsetLeft + 10 + "px"
}

优化后:使用变量缓存需要的值,只获取一次// 缓存offset变量

const el = document.getElementById('el')
let offLeft = el.offsetLeft, offTop = el.offsetTop
// 在JS中对总的偏移量进行计算
for(let i=0;i<10;i++) {
 offLeft += 10
 offTop += 10
}
// 在DOM中修改偏移量
el.style.left = offLeft + "px"
el.style.top = offTop + "px"
...全文
53 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

857

社区成员

发帖
与我相关
我的任务
社区描述
中南民族大学CSDN高校俱乐部聚焦校内IT技术爱好者,通过构建系统化的内容和运营体系,旨在将中南民族大学CSDN社区变成校内最大的技术交流沟通平台。
经验分享 高校 湖北省·武汉市
社区管理员
  • c_university_1575
  • WhiteGlint666
  • wzh_scuec
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

欢迎各位加入中南民族大学&&CSDN高校俱乐部社区(官方QQ群:908527260),成为CSDN高校俱乐部的成员具体步骤(必填),填写如下表单,表单链接如下:
人才储备数据库及线上礼品发放表单邀请人吴钟昊:https://ddz.red/CSDN
CSDN高校俱乐部是给大家提供技术分享交流的平台,会不定期的给大家分享CSDN方面的相关比赛以及活动或实习报名链接,希望大家一起努力加油!共同建设中南民族大学良好的技术知识分享社区。

注意:

1.社区成员不得在社区发布违反社会主义核心价值观的言论。

2.社区成员不得在社区内谈及政治敏感话题。

3.该社区为知识分享的平台,可以相互探讨、交流学习经验,尽量不在社区谈论其他无关话题。

试试用AI创作助手写篇文章吧