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.
Out of the box, One handles:
#element-id when present in the URLYou don’t need to add ScrollBehavior unless you want to change this behavior.
Add ScrollBehavior once in your root layout:
import { ScrollBehavior, Slot } from 'one'
export default function Layout() { return ( <> <ScrollBehavior /> <Slot /> </> )}| Prop | Type | Default | Description |
|---|---|---|---|
disable | boolean | 'restore' | false | Disable scroll behavior entirely or just restoration |
// Disable all scroll behavior<ScrollBehavior disable />
// Disable only scroll restoration on back/forward// (still scrolls to top on new navigation)<ScrollBehavior disable="restore" />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:
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.
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>}#section), scrolls to that elementScroll positions are stored per-pathname in sessionStorage, so they persist across page refreshes within a session but not across browser sessions.
| Platform | Support |
|---|---|
| Web | Full support |
| React Native | Not applicable (no window scroll) |
ScrollBehavior is a web-only component. On native platforms, scroll restoration is handled by the native scroll views themselves.
Preserve scroll position when users navigate away and back:
import { Slot, useScrollGroup } from 'one'
export default function FeedLayout() { // Preserve scroll in the feed when viewing details useScrollGroup()
return <Slot />}Keep each tab’s scroll position independent:
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> )}Don’t scroll when opening modals:
<Link href="/modal" scroll={false}> Open Modal</Link>Edit this page on GitHub.