Prevent Scroll Restoration After Refresh

A hands-on demo of the browser behavior, the native History API switch, the two supported values, and a fallback pattern for older browsers.

1. Browser Default Behavior

With automatic restoration, a refreshed page can return to the scroll position the user was viewing.

Code:
function runAutoDemo() {
  if ('scrollRestoration' in history) {
    history.scrollRestoration = 'auto';
  }

  const scroller = document.querySelector('#auto-demo .demo-window');
  sessionStorage.setItem('auto-demo-scroll', scroller.scrollTop);

  scroller.scrollTop = 0;
  requestAnimationFrame(() => {
    scroller.scrollTop = Number(sessionStorage.getItem('auto-demo-scroll') || 0);
  });
}
Result:
Scroll the demo, then simulate refresh.
Top of demo page
Section ABrowsers usually preserve scroll position during a normal refresh.
Section BThis simulated page stores the current scrollTop value.
Section CAfter the simulated refresh, the saved position is applied again.
Section DThe viewport returns to the same place instead of staying at the top.
Section EThis is helpful most of the time, but not always what an app wants.

2. Disable Restoration with history.scrollRestoration

Set the native property to manual before reload, and the browser should not restore the old scroll position.

Code:
function runManualDemo() {
  if ('scrollRestoration' in history) {
    history.scrollRestoration = 'manual';
  }

  const scroller = document.querySelector('#manual-demo .demo-window');
  sessionStorage.setItem('manual-demo-scroll', scroller.scrollTop);

  scroller.scrollTop = 0;
}
Result:
Manual restoration keeps the demo at the top.
Top of demo page
Section AThe scroll position is still observed before refresh.
Section BThe important difference is the manual setting.
Section CAfter refresh, the demo stays at scrollTop 0.
Section DThis mirrors the behavior developers often want for reset-style pages.
Section ENo timer is needed when the browser supports the API.

3. The Two Supported Values

The property accepts auto and manual. Toggle them below and watch the simulated refresh behavior change.

Code:
function setScrollRestoration(mode) {
  if ('scrollRestoration' in history) {
    history.scrollRestoration = mode;
  }

  document.querySelector('#mode-value').textContent = mode;
}
Result:
Current mode: auto

auto

The browser is allowed to restore the previous scroll position.

manual

The page controls the scroll position itself after navigation or refresh.

Top of demo page
Section AThe buttons above change the same property shown in the code.
Section BWith auto, simulated refresh restores this area.
Section CWith manual, simulated refresh resets to the top.
Section DThis makes the behavior explicit and easy to reason about.
Section EThe live result uses the current value displayed above.

4. Timer Fallback for Unsupported Browsers

When the property is unavailable, the old workaround is to force the scroll position after load.

Code:
function fallbackToTop() {
  if (!('scrollRestoration' in history)) {
    setTimeout(() => {
      window.scrollTo(0, 0);
    }, 250);
  }
}
Result:
The fallback waits briefly, then resets scroll.
Top of demo page
Section AThis showcase animates the timer workaround inside the demo container.
Section BThe real fallback code uses window.scrollTo after a delay.
Section CIt is less elegant because timing can be fragile.
Section DUse the native property when available.
Section EThe timer approach is mainly for old browser requirements.