Skip to content

Control Panel doesn't scroll to top on navigation #14954

Description

@helloDanuk

Bug description

Navigating between CP pages doesn't reset the scroll position: after scrolling down a tall page and clicking a link, the next page opens scrolled down instead of at the top. Cause: the real scroll container #main-content isn't marked as an Inertia [scroll-region], so Inertia's reset (which only touches window + scroll-regions) never resets it. It's masked on short pages because scrollTop clamps to ~0.

  • Expected: Navigating to a new page shows it scrolled to the top (scrollTop = 0).
  • Actual: The previous scroll position is retained (clamped to the destination page's max scroll height).
Bildschirmaufnahme.2026-07-08.um.01.11.58.mov

How to reproduce

  1. Open a CP page that is taller than the viewport (e.g. a long collection listing, a Blueprint list, Fields). Tip: make the browser window short so overflow is guaranteed.
  2. Scroll the content area down.
  3. Navigate to another CP page via a normal link (Inertia visit).
  4. The new page opens scrolled down, not at the top.

This affects any navigation where the destination page is tall enough to hold the previous scroll position — it is not specific to one page.

⚠️ Don't test this on the Dashboard. Its widgets mount asynchronously, so on arrival the page is momentarily short and scrollTop clamps to 0 — which masks the bug and makes it look fine. The Dashboard is the exception that hides the problem; test on a synchronously rendered page instead.

Root cause

The real scroll container in the CP is #main-content (overflow-y-auto in the CP layout). The window itself never scrolls.

Inertia's scroll manager only resets the window and elements carrying the scroll-region attribute:

static regions(){ return document.querySelectorAll(`[scroll-region]`) }

#main-content is not marked with scroll-region, and window.scrollY is always 0, so Inertia's reset has nothing to act on → the scroll position persists across navigations.

Not the same as #14838

#14838 / #14854 (preventScroll: true on #content-card.focus()) fixed the small ~8px focus jump. Note that the previous focus() without preventScroll incidentally scrolled #main-content back to the top on each navigation; removing it (correctly) also removed that accidental reset — so this issue is now more exposed, not less.

Suggested fix

Mark #main-content with the scroll-region attribute so Inertia manages both reset (on navigation) and restore (on browser back/forward) natively. As a userland workaround, setting the attribute once after boot resolves it:

Statamic.booted(() => {
  const mark = () => {
    const el = document.getElementById('main-content');
    if (el) el.setAttribute('scroll-region', '');
    else requestAnimationFrame(mark); // layout may not be mounted yet
  };
  mark();
});

Ideally the attribute would be added directly on the #main-content element in the CP layout.

Logs

Environment

Environment
Laravel Version: 13.19.0
PHP Version: 8.4.22
Composer Version: 2.9.5
Environment: local
Debug Mode: ENABLED
Maintenance Mode: OFF
Timezone: UTC
Locale: en

Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED

Drivers
Broadcasting: log
Cache: file
Database: sqlite
Logs: stack / single
Mail: log
Queue: sync
Session: file

Storage
public/storage: NOT LINKED

Statamic
Addons: 0
License Key: Not set
Sites: 1
Stache Watcher: Enabled (auto)
Static Caching: Disabled
Version: 6.24.1 PRO

Installation

Fresh statamic/statamic site via CLI

Additional details

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions