Describe the bug
Session Replay correctly captures DOM mutations (React state updates, content changes,
etc.) but does not capture or restore the scrollTop position of inner scrollable
elements (overflow-auto / overflow-scroll divs). When the session is replayed, the inner
scroll container always renders from scrollTop = 0, making the replay show completely
different content than what the user actually saw.
This is a significant issue for SPAs that use overflow-hidden on body/main and implement
scrolling via inner container elements — which is a common architectural pattern.
To Reproduce
Steps to reproduce the behavior:
- Create a page where body has overflow: hidden and scrolling is handled by an inner
div with overflow: auto or overflow: scroll
- Populate the scroll container with a large list of content (e.g., 365 rows
representing calendar dates)
- On page load, programmatically scroll the inner container to a position other than 0
(e.g., using scrollIntoView or scrollTop = X to jump to the current date, which sits in
the middle of the list)
- Initialize Datadog RUM and start session replay recording
- Interact with the page (clicks, hovers, etc.)
- View the session replay in Datadog
Expected behavior
The session replay should restore the scroll position of the inner container to match
where the user actually scrolled to. If the user scrolled to row 167 out of 365, the
replay should show row 167 — the same content the user saw.
Actual behavior
The replay always renders the inner scroll container at scrollTop = 0 (the very top of
the container). Since the initial DOM load includes content starting from ~6 months
before the current date (for the calendar use case), the replay shows September 2025
dates when the user was actually viewing March 2026. The date range header (a DOM
mutation) updates correctly in the replay — but the grid content underneath shows the
wrong position because the scroll was never restored.
Environment
- @datadog/browser-rum: 6.30.1 (latest stable, also reproduced on 6.18.1)
- Framework: Next.js 16 (App Router) / React 19
- Browser: Chrome (latest)
Technical Context
Our application layout:
On page load, we call:
dateElement.scrollIntoView({ behavior: "instant", block: "start" });
This scrolls the nearest scrollable ancestor (#scroll-container), not the window. The
window.scrollY remains 0 throughout the entire session. All user scrolling happens on
#scroll-container.
We believe the session replay's scroll capture mechanism only tracks window.scrollX/Y,
and either does not capture scroll events on non-window elements, or captures them but
does not correctly restore them during playback. The result is that any SPA with a
full-height layout and inner scroll containers will produce broken session replays — the
visual state shown will not match the user's actual experience.
Describe the bug
Session Replay correctly captures DOM mutations (React state updates, content changes,
etc.) but does not capture or restore the scrollTop position of inner scrollable
elements (overflow-auto / overflow-scroll divs). When the session is replayed, the inner
scroll container always renders from scrollTop = 0, making the replay show completely
different content than what the user actually saw.
This is a significant issue for SPAs that use overflow-hidden on body/main and implement
scrolling via inner container elements — which is a common architectural pattern.
To Reproduce
Steps to reproduce the behavior:
div with overflow: auto or overflow: scroll
representing calendar dates)
(e.g., using scrollIntoView or scrollTop = X to jump to the current date, which sits in
the middle of the list)
Expected behavior
The session replay should restore the scroll position of the inner container to match
where the user actually scrolled to. If the user scrolled to row 167 out of 365, the
replay should show row 167 — the same content the user saw.
Actual behavior
The replay always renders the inner scroll container at scrollTop = 0 (the very top of
the container). Since the initial DOM load includes content starting from ~6 months
before the current date (for the calendar use case), the replay shows September 2025
dates when the user was actually viewing March 2026. The date range header (a DOM
mutation) updates correctly in the replay — but the grid content underneath shows the
wrong position because the scroll was never restored.
Environment
Technical Context
Our application layout:
On page load, we call:
dateElement.scrollIntoView({ behavior: "instant", block: "start" });
This scrolls the nearest scrollable ancestor (#scroll-container), not the window. The
window.scrollY remains 0 throughout the entire session. All user scrolling happens on
#scroll-container.
We believe the session replay's scroll capture mechanism only tracks window.scrollX/Y,
and either does not capture scroll events on non-window elements, or captures them but
does not correctly restore them during playback. The result is that any SPA with a
full-height layout and inner scroll containers will produce broken session replays — the
visual state shown will not match the user's actual experience.