CSS之重绘与回流

重绘(Repaint)

当页面中元素样式的改变并不影响它在文档流中的位置时(例如改变颜色、阴影等),浏览器会进行重绘,即重新绘制元素的外观。

回流(Reflow)

当元素的大小、位置、隐藏等改变时,浏览器需要重新计算元素的几何信息,并重新渲染页面,这个过程称为回流。会影响当前元素、祖先元素和后代元素。

性能影响

  • 回流比重绘的代价要高。回流的过程比重绘复杂,因为它涉及到更多的计算。
  • 回流必将引发重绘,而重绘不一定会引发回流。

触发条件

  • 添加或删除可见的DOM元素
  • 元素尺寸改变
  • 内容变化,例如用户在input框中输入文字
  • 页面渲染初始化
  • 浏览器窗口尺寸改变 ------ 触发重排(回流)。

如何减少重绘和回流

  • 使用transform替代top。
  • 使用visibility替换display: none ------ 因为前者只会触发重绘,后者会触发回流(重排)。
  • 不要使用table布局,因为可能很小的一个小改动会导致整个table的重新布局。
  • 避免在循环中对DOM进行频繁操作,可以使用documentFragment进行批量操作。
  • 避免频繁地读取会引发回流/重绘的属性,如果需要多次使用,可以用变量缓存起来。

代码示例

回流

HTML:

html 复制代码
<div id="container">
    <p>Some text here...</p>
</div>

JavaScript:

javascript 复制代码
let container = document.getElementById('container');

// 这里会触发回流,因为改变了元素的几何属性
container.style.padding = '20px';

// 这又触发了一次回流
container.style.borderWidth = '5px';

为了减少回流,可以合并多次改变样式的操作,使用cssText合并成一次操作:

javascript 复制代码
container.style.cssText = 'padding: 20px; border-width: 5px;';

或者使用CSS类:

css 复制代码
.custom-style {
    padding: 20px;
    border-width: 5px;
}
javascript 复制代码
container.classList.add('custom-style');

重绘

CSS:

css 复制代码
<head>
    <style>
        .box {
            width: 100px;
            height: 100px;
            background-color: blue;
        }
    </style>
</head>
<body>
    <div class="box"></div>
</body>

JavaScript:

javascript 复制代码
document.querySelector('.box').style.backgroundColor = 'red';

这段代码改变了盒子的外观而没有改变它的布局,因此仅仅会导致重绘。

减少重绘和回流

1.使用cssText或者CSS类代替多次DOM操作

2. 使用fragment或clone

当需要对DOM进行大量修改时,最好的做法是使用DocumentFragment或者是clone一个元素,在副本上进行所有操作,然后再把它放回文档中。

javascript 复制代码
let list = document.getElementById('list'),
    frag = document.createDocumentFragment(),
    items = ['Item 1', 'Item 2', 'Item 3'];

// 使用DocumentFragment作操作
items.forEach(item => {
    let li = document.createElement('li');
    li.textContent = item;
    frag.appendChild(li);
});

// 把DocumentFragment一次性添加到DOM中,减少页面回流
list.appendChild(frag);

这样做的好处在于减少了页面的回流次数:不是每添加一个列表项就回流一次,而是所有项都准备好之后才触发一次回流。

相关推荐
也无晴也无风雨24 分钟前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational2 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、4 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤5 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui