v150 · css · scroll
Programmatic scroll promises
All programmatic scroll methods on Element and Window — scrollTo(), scrollBy(), scroll(), and scrollIntoView() — now return Promise objects that resolve when the scroll completes or is interrupted, giving reliable completion signals for smooth-scroll animations.
at a glance
| Shipped in | Chrome 150 (Enabled by default) |
|---|---|
| Status | Enabled by default |
| Standards position (Firefox) | No signal |
| Standards position (Safari) | Shipped/Shipping |
| Spec issue | w3c/csswg-drafts issue #1562 |
| ChromeStatus | 5082138340491264 — Programmatic scroll promises |
why it exists
Before this change, element.scrollTo({ behavior: 'smooth', ... }) returned undefined. Developers who needed to know when a smooth scroll finished had to resort to IntersectionObserver, polling scrollTop, or listening to the scroll event and debouncing it. None of those approaches cleanly distinguished between "scroll is still in flight" and "scroll has settled".
The Promise-returning scroll methods provide a first-class completion signal. The returned Promise resolves with undefined when the scroll reaches its destination, or when it is interrupted (e.g. by another scroll, layout change, or user interaction). A rejected Promise indicates an error (e.g. element was removed).
shape of the API
| Method | Old return type | New return type |
|---|---|---|
Element.scrollTo(options) | void | Promise<void> |
Element.scrollBy(options) | void | Promise<void> |
Element.scroll(options) | void | Promise<void> |
Element.scrollIntoView(options) | void | Promise<void> |
Window.scrollTo(options) | void | Promise<void> |
Window.scrollBy(options) | void | Promise<void> |
Window.scroll(options) | void | Promise<void> |
The two-argument forms (scrollTo(x, y), scrollBy(x, y)) continue to return undefined for backwards-compatibility; pass an options object to get a Promise.
example
// Await a smooth scroll to the top, then run an animation
await document.documentElement.scrollTo({ top: 0, behavior: 'smooth' });
revealHeroAnimation();
// Chain multiple smooth scrolls
async function scrollTour(sections) {
for (const section of sections) {
await section.scrollIntoView({ behavior: 'smooth', block: 'start' });
await highlightSection(section);
}
}
// Instant scrolls also return a Promise (already resolved)
await window.scrollTo({ top: 500 }); // resolves immediately
console.log('done');
// Feature detection
const scroll = document.documentElement.scrollTo({ top: 0 });
if (scroll instanceof Promise) {
console.log('Promise-returning scrolls supported');
}
Source: CSSWG issue #1562
browser support
| Browser | Support | Notes |
|---|---|---|
| Chrome 150+ | Enabled by default | All platforms |
| Safari | Shipped/Shipping | Also supported |
| Firefox | No signal | — |