Bird
Raised Fist0
NextJSframework~15 mins

Scroll behavior control in NextJS - Deep Dive

Choose your learning style10 modes available
Overview - Scroll behavior control
What is it?
Scroll behavior control in Next.js means managing how the page moves up or down when users navigate between pages or interact with the site. It lets you decide if the page should jump instantly, smoothly glide, or stay in place when changing views. This helps create a better experience by guiding the user's eyes naturally. Without it, navigation can feel jarring or confusing.
Why it matters
Without scroll behavior control, users might lose their place on a page or feel disoriented when moving around a website. For example, clicking a link might suddenly jump to the top, making users lose context. Controlling scroll behavior makes navigation feel smooth and intentional, improving usability and keeping users engaged.
Where it fits
Before learning scroll behavior control, you should understand basic Next.js routing and React component structure. After mastering scroll control, you can explore advanced user experience techniques like animations, lazy loading, and state management tied to scroll position.
Mental Model
Core Idea
Scroll behavior control is about deciding how and when the page moves vertically during navigation to create smooth, predictable user experiences.
Think of it like...
It's like guiding someone through a photo album: you can flip pages quickly, slowly, or pause to focus on a picture, making the journey comfortable and clear.
┌─────────────────────────────┐
│ User clicks a link or event │
└─────────────┬───────────────┘
              │
      ┌───────▼────────┐
      │ Scroll Behavior │
      │   Decision     │
      └───────┬────────┘
              │
  ┌───────────▼───────────┐
  │ Instant jump to target │
  ├───────────────────────┤
  │ Smooth scroll to target│
  ├───────────────────────┤
  │ No scroll (stay put)   │
  └───────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding default scroll behavior
🤔
Concept: Learn how Next.js handles scrolling by default when navigating between pages.
By default, Next.js scrolls to the top of the page when you navigate to a new route. This means the user always starts at the top of the new page automatically. This behavior is built-in and requires no extra code.
Result
When you click a link to a new page, the browser jumps instantly to the top of that page.
Knowing the default helps you understand why sometimes users lose their scroll position and why you might want to customize this behavior.
2
FoundationUsing the Link component for navigation
🤔
Concept: Learn how Next.js's Link component triggers navigation and affects scroll behavior.
Next.js provides a Link component to navigate between pages without full reloads. When you use Link, Next.js handles the route change and scrolls to the top by default. You can customize this behavior by adding props or handling events.
Result
Clicking a Link changes the page and scrolls to the top automatically.
Understanding Link is key because scroll behavior control often ties into how navigation happens.
3
IntermediateControlling scroll with router events
🤔Before reading on: do you think you can stop scrolling by default using router events? Commit to yes or no.
Concept: Next.js exposes router events that let you run code during navigation, allowing you to control scroll behavior manually.
You can listen to router events like 'routeChangeComplete' to run code after navigation finishes. For example, you can scroll to a specific position or prevent scrolling by overriding default behavior. This requires using the useRouter hook and window.scrollTo or similar methods.
Result
You can customize where the page scrolls after navigation, such as staying in place or scrolling smoothly to a section.
Knowing router events unlocks precise control over scroll behavior beyond defaults.
4
IntermediateUsing scrollRestoration for back/forward buttons
🤔Before reading on: does the browser always restore scroll position automatically on back navigation in Next.js? Commit to yes or no.
Concept: The browser has a scrollRestoration API that controls if scroll position is saved and restored when using back/forward buttons. Next.js can use this to improve user experience.
By default, Next.js disables scrollRestoration to avoid conflicts. You can enable it manually in a useEffect hook to let the browser remember scroll positions when users navigate back or forward, making navigation feel natural.
Result
When users click back, the page scrolls to where they left off instead of jumping to the top.
Understanding scrollRestoration helps you fix confusing scroll jumps during back/forward navigation.
5
IntermediateImplementing smooth scroll behavior
🤔Before reading on: do you think smooth scrolling requires complex libraries or can be done with simple browser APIs? Commit to your answer.
Concept: Modern browsers support smooth scrolling natively, which you can trigger with simple JavaScript or CSS to improve scroll transitions.
You can call window.scrollTo with behavior: 'smooth' to glide the page to a position instead of jumping. Alternatively, CSS property scroll-behavior: smooth can make all scrolls smooth automatically. This creates a nicer visual effect during navigation or user actions.
Result
Page scrolls smoothly to the target position instead of jumping instantly.
Knowing native smooth scroll APIs lets you enhance UX without extra dependencies.
6
AdvancedCustom scroll restoration with saved positions
🤔Before reading on: do you think you can save scroll positions manually to restore them later? Commit to yes or no.
Concept: You can build your own scroll restoration system by saving scroll positions in memory or storage and restoring them on navigation, giving full control over scroll state.
By listening to router events, you save the current scroll position before navigating away. When returning, you read the saved position and scroll there manually. This is useful for complex apps where default restoration is insufficient, like dynamic content or infinite scroll pages.
Result
Users return to exactly where they left off, even across complex navigation flows.
Understanding manual scroll restoration empowers you to build seamless experiences in complex apps.
7
ExpertHandling scroll with dynamic content and hydration
🤔Before reading on: do you think scroll position is always reliable immediately after navigation in Next.js? Commit to yes or no.
Concept: In Next.js, pages often load content dynamically or hydrate React components after navigation, which can change page height and affect scroll position accuracy.
If you scroll immediately after navigation, the page might not have fully loaded content, causing scroll jumps or wrong positions. Experts delay scroll restoration until content is ready, using techniques like waiting for images to load or React hydration to complete. This ensures scroll position is accurate and stable.
Result
Scroll position matches user expectation without sudden jumps or flickers after navigation.
Knowing how dynamic content affects scroll lets you avoid subtle bugs that frustrate users in real apps.
Under the Hood
Next.js uses the browser's History API to change routes without full reloads. When navigation happens, Next.js triggers events and updates the URL. By default, it scrolls the window to the top. The browser also has a scrollRestoration property that can save and restore scroll positions on back/forward navigation. Developers can hook into router events to override or enhance this behavior by calling window.scrollTo or manipulating scroll containers.
Why designed this way?
Next.js aims for fast, seamless navigation like a single-page app but with server-side rendering benefits. Default scroll to top matches user expectations for new pages. However, scroll restoration is disabled by default to avoid conflicts with dynamic content loading and React hydration. This design balances simplicity for most cases with flexibility for advanced control.
┌───────────────┐
│ User triggers │
│ navigation    │
└───────┬───────┘
        │
┌───────▼─────────────┐
│ Next.js Router      │
│ updates URL & state │
└───────┬─────────────┘
        │
┌───────▼─────────────┐
│ Router Events fire  │
│ (routeChangeStart,  │
│  routeChangeComplete)│
└───────┬─────────────┘
        │
┌───────▼─────────────┐
│ Scroll Behavior Code │
│ (default or custom)  │
└───────┬─────────────┘
        │
┌───────▼─────────────┐
│ Browser scroll moves │
│ window or container  │
└─────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does Next.js automatically restore scroll position on back navigation? Commit to yes or no.
Common Belief:Next.js always restores scroll position automatically when using back or forward buttons.
Tap to reveal reality
Reality:By default, Next.js disables browser scroll restoration, so scroll position is not restored unless you enable it manually.
Why it matters:Assuming automatic restoration leads to confusing user experiences with unexpected scroll jumps on back navigation.
Quick: Is smooth scrolling only possible with external libraries? Commit to yes or no.
Common Belief:You need third-party libraries to implement smooth scrolling in Next.js.
Tap to reveal reality
Reality:Modern browsers support smooth scrolling natively via CSS or JavaScript APIs without extra libraries.
Why it matters:Believing this causes unnecessary complexity and larger bundle sizes.
Quick: Does scrolling immediately after navigation always work correctly? Commit to yes or no.
Common Belief:You can scroll to any position right after route change and it will be accurate.
Tap to reveal reality
Reality:Dynamic content loading and React hydration can change page height after navigation, making immediate scroll unreliable.
Why it matters:Ignoring this causes flickering scroll jumps and poor user experience.
Quick: Does disabling scroll on navigation mean the page never moves? Commit to yes or no.
Common Belief:If you disable scroll on navigation, the page will never scroll even when needed.
Tap to reveal reality
Reality:You can selectively control scroll behavior to keep position or scroll to specific places as needed.
Why it matters:Misunderstanding this limits creative scroll control and harms UX.
Expert Zone
1
Scroll restoration must consider asynchronous data loading to avoid jumping scroll positions after content changes.
2
Using router events for scroll control requires careful cleanup to prevent memory leaks or conflicting scroll commands.
3
Custom scroll containers (not window) need manual scroll management since browser APIs default to window scrolling.
When NOT to use
Avoid custom scroll control when your app has simple static pages where default behavior suffices. For very complex scroll interactions, consider dedicated libraries like react-scroll or full-page scroll frameworks instead of manual control.
Production Patterns
In production, developers combine router event listeners with saved scroll positions in session storage to restore user context. Smooth scroll is often enabled globally via CSS for consistent feel. Complex apps delay scroll restoration until data fetching completes to avoid jumps.
Connections
Single Page Application (SPA) Routing
Scroll behavior control builds on SPA routing concepts by managing page position during client-side navigation.
Understanding SPA routing helps grasp why scroll control is needed to mimic traditional page loads smoothly.
User Experience Design
Scroll behavior control directly impacts UX by guiding user attention and reducing confusion during navigation.
Knowing UX principles clarifies why smooth and predictable scrolling improves user satisfaction.
Memory Management in Operating Systems
Like saving and restoring scroll positions, OS memory management saves and restores process states to maintain continuity.
This cross-domain link shows how saving state for smooth transitions is a universal pattern in computing.
Common Pitfalls
#1Page jumps to top immediately after navigation even when you want to keep scroll position.
Wrong approach:router.events.on('routeChangeComplete', () => { // No scroll control here });
Correct approach:router.events.on('routeChangeComplete', () => { window.scrollTo({ top: savedPosition, behavior: 'auto' }); });
Root cause:Not handling scroll manually after navigation leaves default scroll to top behavior active.
#2Scroll restoration breaks because scrollRestoration is not enabled.
Wrong approach:useEffect(() => { // No scrollRestoration setup }, []);
Correct approach:useEffect(() => { if ('scrollRestoration' in window.history) { window.history.scrollRestoration = 'auto'; } }, []);
Root cause:Assuming browser handles scroll restoration without enabling it in Next.js.
#3Smooth scroll causes flicker because it runs before content loads.
Wrong approach:router.events.on('routeChangeComplete', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); });
Correct approach:router.events.on('routeChangeComplete', () => { setTimeout(() => { window.scrollTo({ top: 0, behavior: 'smooth' }); }, 100); // wait for content });
Root cause:Triggering scroll before dynamic content finishes loading causes visual jumps.
Key Takeaways
Next.js scroll behavior control lets you manage how the page moves during navigation to improve user experience.
By default, Next.js scrolls to the top on new pages and disables browser scroll restoration on back/forward navigation.
You can use router events and browser APIs to customize scroll position, enable smooth scrolling, and restore scroll state manually.
Handling dynamic content loading and hydration timing is crucial to avoid scroll position bugs.
Expert scroll control balances default simplicity with advanced manual techniques for seamless, intuitive navigation.

Practice

(1/5)
1. What does setting behavior: 'smooth' in window.scrollTo do in a Next.js app?
easy
A. It reloads the page after scrolling.
B. It makes the page scroll smoothly instead of jumping instantly.
C. It scrolls the page to the top instantly.
D. It disables scrolling on the page.

Solution

  1. Step 1: Understand the scroll behavior option

    The behavior property controls how scrolling happens. Setting it to 'smooth' means the scroll moves gradually.
  2. Step 2: Apply to Next.js scrolling

    Using window.scrollTo({ behavior: 'smooth' }) in Next.js makes the page scroll smoothly instead of jumping instantly.
  3. Final Answer:

    It makes the page scroll smoothly instead of jumping instantly. -> Option B
  4. Quick Check:

    behavior: 'smooth' = smooth scrolling [OK]
Hint: Remember 'smooth' means gradual scroll, not instant jump [OK]
Common Mistakes:
  • Thinking 'smooth' disables scrolling
  • Confusing 'smooth' with instant scroll
  • Assuming it reloads the page
2. Which of the following is the correct syntax to scroll smoothly to the top of the page in Next.js?
easy
A. window.scrollTo({ smooth: 'top' });
B. window.scrollTo(0, 0, 'smooth');
C. window.scrollTo({ top: 0, smooth: true });
D. window.scrollTo({ top: 0, behavior: 'smooth' });

Solution

  1. Step 1: Review window.scrollTo syntax

    The correct syntax uses an object with top and behavior keys: { top: 0, behavior: 'smooth' }.
  2. Step 2: Identify correct option

    window.scrollTo({ top: 0, behavior: 'smooth' }); matches the correct syntax. Others misuse parameters or keys.
  3. Final Answer:

    window.scrollTo({ top: 0, behavior: 'smooth' }); -> Option D
  4. Quick Check:

    Correct scrollTo syntax = window.scrollTo({ top: 0, behavior: 'smooth' }); [OK]
Hint: Use object with top and behavior keys for smooth scroll [OK]
Common Mistakes:
  • Passing parameters as separate arguments instead of object
  • Using incorrect keys like 'smooth' instead of 'behavior'
  • Misplacing the 'smooth' value
3. Consider this Next.js code snippet inside a component:
<pre>useEffect(() => { router.events.on('routeChangeComplete', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); }, []);
What will happen when the route changes?
medium
A. The page will smoothly scroll to the top after navigation.
B. Nothing will happen because the event listener is not removed.
C. The page will jump instantly to the top.
D. The page will reload after scrolling.

Solution

  1. Step 1: Understand event listener on routeChangeComplete

    The code listens for the route change completion event and triggers scrolling.
  2. Step 2: Analyze scrollTo call

    It calls window.scrollTo with behavior: 'smooth', so scrolling is smooth to top.
  3. Final Answer:

    The page will smoothly scroll to the top after navigation. -> Option A
  4. Quick Check:

    routeChangeComplete + smooth scroll = smooth scroll top [OK]
Hint: routeChangeComplete triggers smooth scroll to top [OK]
Common Mistakes:
  • Assuming instant jump instead of smooth scroll
  • Thinking event listener removal is required to trigger scroll
  • Confusing scroll with page reload
4. This Next.js code tries to scroll smoothly on route change:
<pre>useEffect(() => { router.events.on('routeChangeComplete', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); }, []);
But after navigating multiple times, scrolling stops working. What is the likely problem?
medium
A. The event listener is added multiple times without cleanup, causing issues.
B. The scrollTo syntax is incorrect and causes errors.
C. Next.js does not support scroll control on route changes.
D. The behavior 'smooth' is not supported in modern browsers.

Solution

  1. Step 1: Identify event listener management

    The code adds an event listener on mount but never removes it, so multiple listeners accumulate.
  2. Step 2: Understand effect of multiple listeners

    Multiple listeners cause unexpected behavior or conflicts, stopping scroll from working properly.
  3. Final Answer:

    The event listener is added multiple times without cleanup, causing issues. -> Option A
  4. Quick Check:

    Missing cleanup causes multiple listeners = problem [OK]
Hint: Always remove event listeners in useEffect cleanup [OK]
Common Mistakes:
  • Ignoring cleanup of event listeners
  • Blaming scrollTo syntax which is correct
  • Assuming browser support is the issue
5. You want to scroll smoothly to a specific section with id 'contact' after navigating to a new page in Next.js. Which approach correctly achieves this?
hard
A. Use window.scrollTo(0, 0); after navigation and then call scrollIntoView without behavior option.
B. Use window.scrollTo({ top: document.getElementById('contact').offsetTop, behavior: 'auto' }); inside routeChangeStart event.
C. Use router.events.on('routeChangeComplete', () => { document.getElementById('contact').scrollIntoView({ behavior: 'smooth' }); });
D. Use router.push('/contact'); without any scroll control; rely on default browser behavior.

Solution

  1. Step 1: Choose correct event and method

    Use routeChangeComplete to ensure page is loaded, then scroll to element with smooth behavior.
  2. Step 2: Verify scrollIntoView usage

    scrollIntoView({ behavior: 'smooth' }) scrolls smoothly to the element with id 'contact'.
  3. Final Answer:

    Use router.events.on('routeChangeComplete', () => { document.getElementById('contact').scrollIntoView({ behavior: 'smooth' }); }); -> Option C
  4. Quick Check:

    routeChangeComplete + scrollIntoView smooth = Use router.events.on('routeChangeComplete', () => { document.getElementById('contact').scrollIntoView({ behavior: 'smooth' }); }); [OK]
Hint: Scroll after routeChangeComplete using scrollIntoView with smooth [OK]
Common Mistakes:
  • Using routeChangeStart instead of routeChangeComplete
  • Forgetting behavior: 'smooth' for smooth scroll
  • Relying on default scroll without control
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard