Skip to content

Commit 0ef46d5

Browse files
authored
Throttling scroll events with requestAnimationFrame is useless (mdn#40859)
1 parent e006f2c commit 0ef46d5

File tree

1 file changed

+7
-4
lines changed
  • files/en-us/web/api/document/scroll_event

1 file changed

+7
-4
lines changed

files/en-us/web/api/document/scroll_event/index.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ A generic {{domxref("Event")}}.
3030

3131
### Scroll event throttling
3232

33-
Since `scroll` events can fire at a high rate, the event handler shouldn't execute computationally expensive operations such as DOM modifications. Instead, it is recommended to {{glossary("throttle")}} the event using {{DOMxRef("Window.requestAnimationFrame()", "requestAnimationFrame()")}}, {{DOMxRef("Window.setTimeout", "setTimeout()")}}, or a {{DOMxRef("CustomEvent")}}, as follows.
33+
Since `scroll` events can fire at a high rate, the event handler shouldn't execute computationally expensive operations such as DOM modifications. If you notice a {{glossary("jank")}} while fast scrolling, you should consider {{glossary("throttle", "throttling")}} the event.
3434

35-
Note, however, that input events and animation frames are fired at about the same rate, and therefore the optimization below is often unnecessary. This example optimizes the `scroll` event for `requestAnimationFrame`.
35+
Note that you may see code that throttles the `scroll` event handler using {{domxref("Window.requestAnimationFrame()", "requestAnimationFrame()")}}. This is _useless_ because animation frame callbacks are fired at the same rate as `scroll` event handlers. Instead, you must measure the timeout yourself, such as by using {{domxref("Window.setTimeout", "setTimeout()")}}.
3636

3737
```js
3838
let lastKnownScrollPosition = 0;
@@ -46,16 +46,19 @@ document.addEventListener("scroll", (event) => {
4646
lastKnownScrollPosition = window.scrollY;
4747

4848
if (!ticking) {
49-
window.requestAnimationFrame(() => {
49+
// Throttle the event to "do something" every 20ms
50+
setTimeout(() => {
5051
doSomething(lastKnownScrollPosition);
5152
ticking = false;
52-
});
53+
}, 20);
5354

5455
ticking = true;
5556
}
5657
});
5758
```
5859

60+
Alternatively, consider using {{domxref("IntersectionObserver")}} instead, which allows threshold-based listening.
61+
5962
## Specifications
6063

6164
{{Specifications}}

0 commit comments

Comments
 (0)