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 — including Element.scrollBy(), Element.scrollIntoView(), and Window.scrollBy() — 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.
API contract disagreement, both sides reported rather than resolved (fetched 2026-10-07): this page says the two-argument forms continue to return undefined for backwards-compatibility, while the cited CSSWG resolution adds returning a promise to all scroll functions and the CSSOM View specification declares the two-argument overloads as returning Promise. Neither side is adjudicated here.
example
// Await a smooth scroll to the top, then run an animation
await document.documentElement.scrollTo({ top: 0, behavior: 'smooth' });
revealHeroAnimation();
// Relative smooth scroll on an element, awaiting completion
await element.scrollBy({ top: 200, behavior: 'smooth' });
onScrollSettled();
// 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 | — |
Support table status disagreement, both sides reported rather than resolved (fetched 2026-10-07): this page records Safari as Shipped/Shipping, while the cited ChromeStatus record reports Support, a positive standards position rather than a shipped status. Neither side is adjudicated here.