<ScrollBehavior />

One automatically handles scroll restoration to provide a native browser-like experience. When you navigate to a new page, scroll resets to the top. When you press back/forward, your previous scroll position is restored.

The ScrollBehavior component lets you customize this behavior for special cases.

Default Behavior

Out of the box, One handles:

  • Hash scrolling: Scrolls to #element-id when present in the URL
  • New page navigation: Scrolls to top when navigating to a new route
  • Back/forward navigation: Restores the previous scroll position
  • Session persistence: Scroll positions are saved to sessionStorage

You don’t need to add ScrollBehavior unless you want to change this behavior.

Usage

Add ScrollBehavior once in your root layout:

app/_layout.tsx

import { ScrollBehavior, Slot } from 'one'
export default function Layout() {
return (
<>
<ScrollBehavior />
<Slot />
</>
)
}

Props

PropTypeDefaultDescription
disableboolean | 'restore'falseDisable scroll behavior entirely or just restoration

Disable Options

// Disable all scroll behavior
<ScrollBehavior disable />
// Disable only scroll restoration on back/forward
// (still scrolls to top on new navigation)
<ScrollBehavior disable="restore" />

Scroll Groups

For complex layouts like tabs or dashboards, you may want child routes to share a scroll position. Use the useScrollGroup hook to create a scroll group:

app/dashboard/_layout.tsx

import { Slot, useScrollGroup } from 'one'
export default function DashboardLayout() {
// All routes under /dashboard will share scroll position
useScrollGroup()
return (
<div>
<Sidebar />
<main>
<Slot />
</main>
</div>
)
}

Now when navigating between /dashboard/overview and /dashboard/settings, the scroll position is preserved instead of resetting to the top.

Custom Scroll Group Path

You can specify a custom group path:

import { useScrollGroup } from 'one'
function MyLayout() {
// Create a scroll group for a specific path
useScrollGroup('/products')
return <Slot />
}

Disable scroll behavior for individual navigation actions using the scroll prop on Link:

import { Link } from 'one'
// This navigation won't affect scroll position
<Link href="/next-page" scroll={false}>
Stay in place
</Link>

Or with useRouter:

import { useRouter } from 'one'
function MyComponent() {
const router = useRouter()
const handleClick = () => {
router.push('/next-page', { scroll: false })
}
return <button onClick={handleClick}>Navigate without scrolling</button>
}

How It Works

  1. On navigation start: Current scroll position is saved to sessionStorage keyed by pathname
  2. On navigation complete:
    • If URL has a hash (#section), scrolls to that element
    • If back/forward navigation, restores saved position
    • If within a scroll group, preserves group position
    • Otherwise, scrolls to top

Scroll positions are stored per-pathname in sessionStorage, so they persist across page refreshes within a session but not across browser sessions.

Platform Support

PlatformSupport
WebFull support
React NativeNot applicable (no window scroll)

ScrollBehavior is a web-only component. On native platforms, scroll restoration is handled by the native scroll views themselves.

Common Use Cases

Infinite Scroll Lists

Preserve scroll position when users navigate away and back:

app/feed/_layout.tsx

import { Slot, useScrollGroup } from 'one'
export default function FeedLayout() {
// Preserve scroll in the feed when viewing details
useScrollGroup()
return <Slot />
}

Tab-Based Navigation

Keep each tab’s scroll position independent:

app/(tabs)/_layout.tsx

import { Tabs, useScrollGroup } from 'one'
export default function TabLayout() {
useScrollGroup()
return (
<Tabs>
<Tabs.Screen name="home" />
<Tabs.Screen name="search" />
<Tabs.Screen name="profile" />
</Tabs>
)
}

Disable for Modal Routes

Don’t scroll when opening modals:

<Link href="/modal" scroll={false}>
Open Modal
</Link>
  • Link - Navigation component with scroll control
  • useRouter - Programmatic navigation with scroll options
  • Layouts - Layout patterns for scroll groups

Edit this page on GitHub.