Skip to content

Scroll & focus management

What should happen to the viewport - and to keyboard/screen-reader focus - after each navigation. All configured once, on BrouterOptions.

The four knobs

These DOM effects run once the matched route is committed, so fragment and focus selectors resolve against the new page. During static prerender they are skipped - there is no DOM to act on.

OptionBehavior
ScrollBehaviorToTop scrolls the window to the top on navigation (default None - SPAs otherwise keep the old scroll position on the new page).
ScrollToFragmentNavigating to /docs#install scrolls #install into view and focuses it. Default on; a found fragment target wins over everything else that navigation.
RestoreScrollPositionRemembers each page's scroll position and restores it on Back/Forward, like native browsers. New navigations still use ScrollBehavior. Default off; enabling takes over history.scrollRestoration.
FocusOnNavigateSelectorMoves focus to a selector (e.g. "h1") after navigation so assistive technologies announce the new page - the SPA-router counterpart of Blazor's <FocusOnNavigate>, and a WCAG-relevant concern. Non-focusable targets get tabindex="-1".
builder.Services.AddBitBrouterServices(o =>
{
    o.ScrollBehavior = BrouterScrollMode.ToTop;
    o.ScrollToFragment = true;
    o.RestoreScrollPosition = true;
    o.ScrollPositionStorage = BrouterScrollPositionStorage.SessionStorage;
    o.FocusOnNavigateSelector = "h1";
});

Where restored positions live

ScrollPositionStorage picks the store for remembered positions: Memory (default - lost on a full reload), SessionStorage (recommended: per-tab, auto-cleared on tab close, survives reloads), or LocalStorage (survives restarts, shared across tabs). If the chosen store is unavailable (private mode, quota), it falls back to memory.

Precedence when several apply

If a fragment target resolves, it scrolls into view and takes focus - nothing else runs that navigation. Otherwise, a Back/Forward with a remembered position restores it, else ScrollBehavior applies; and only in these non-fragment cases does FocusOnNavigateSelector then receive focus.

Navigation type awareness

Scroll restoration is driven by BrouterNavigationContext.NavigationType (Push / Replace / Pop) - the same signal your own guards, loaders and hooks can branch on for "treat Back differently" logic like reusing cached data on a Pop. See navigation & history.