Skip to content

一、先给结论

  • 会有影响,但大多数情况下影响很小;
  • 真正有性能风险的是:
  • 「大量 overflow: scroll + 自定义滚动条样式 + 高频滚动」

换句话说:

  • 原生滚动条:几乎不用担心
  • 自定义滚动条(尤其 WebKit 样式):需要控制数量

二、为什么“很多滚动条”可能影响性能?

我们从浏览器底层实现来看。

三、滚动在浏览器里是怎么实现的?

1️⃣ 原生滚动(最佳情况)

  • 滚动 ≠ 重新 Layout

  • 多数情况下是:

    Composite(GPU 位移)
  • 浏览器会把可滚动区域当成一个独立滚动层

👉 极快

2️⃣ overflow: scroll 做了什么?

  • 创建一个 scroll container

  • 浏览器需要维护:

    • scroll offset
    • clipping 区域
    • scroll event dispatch

📌 scroll 本身是 cheap 的

四、性能问题真正出现在哪?

🔥 重点:自定义滚动条样式

css
::-webkit-scrollbar
::-webkit-scrollbar-thumb
::-webkit-scrollbar-track

自定义后会发生什么?

  • 滚动条变成:

    • 普通 DOM 绘制的一部分
  • 滚动过程中:

    • 需要参与 Paint
    • 不能完全走原生合成路径

📉 Paint 次数 ↑

五、很多滚动条 + 自定义样式 = 风险点

典型高风险场景

text
页面上有 50~100 个
overflow: scroll 的容器
并且:
- 都使用了 ::-webkit-scrollbar 样式
- 同时滚动(如列表、拖拽)

可能导致:

  • Paint 频繁
  • 合成层过多
  • 滚动卡顿(尤其低端设备)

六、DevTools 怎么验证?

1️⃣ 打开 Paint flashing

DevTools → Rendering → Paint flashing

2️⃣ 滚动页面

原生滚动条:

  • 几乎无绿色闪烁

自定义滚动条:

  • 滚动条区域频繁闪绿
  • FPS 下降

👉 这是 Paint 的证据

七、全局设置滚动条样式,会不会影响“所有滚动”?

CSS 示例:

css
* {
  scrollbar-width: thin;            /* Firefox */
}

::-webkit-scrollbar {
  width: 6px;
}

浏览器行为:

  • 只作用于可滚动容器

  • 不会平白创建滚动条

  • 但:

    • 每个 scroll container 都会应用样式

📌 样式本身不贵,滚动时的 Paint 才是成本

八、什么情况下可以放心用?

✅ 安全场景

  • 滚动容器数量少(< 10)
  • 滚动频率低
  • 主要是桌面端
  • 不在动画/拖拽中滚动

⚠️ 需要谨慎

  • 大型后台系统
  • 虚拟列表
  • 多嵌套滚动区域
  • 移动端 WebView

九、工程级最佳实践

1️⃣ 能不用 scroll 就不用

  • 页面级滚动优于局部滚动
  • 减少嵌套滚动区域

2️⃣ 只给“关键区域”自定义

css
/* ❌ 全局 */
::-webkit-scrollbar {}

/* ✅ 指定容器 */
.list::-webkit-scrollbar {}

3️⃣ 使用 overflow: auto 而非 scroll

css
/* ❌ 永远显示滚动条 */
overflow: scroll;

/* ✅ 需要时才显示 */
overflow: auto;

减少:

  • scroll container 数量
  • 合成层压力

4️⃣ 避免滚动条动画

css
/* ❌ */
::-webkit-scrollbar-thumb {
  transition: all 0.3s;
}

滚动时会触发 repaint

5️⃣ 大列表用“虚拟滚动”

(React / Vue 场景)

  • react-window
  • vue-virtual-scroller

十、总结

  • 浏览器的原生滚动通常可以在合成阶段完成,性能很好。
  • 但如果对滚动条进行自定义样式,滚动条会参与绘制,
  • 在大量 overflow: scroll 容器和高频滚动场景下,
  • 可能会增加 Paint 和合成开销。
  • 因此工程上应避免全局自定义滚动条样式,
  • 并减少嵌套滚动容器数量。