Skip to content

Scroll Behavior | Vue Router - Control Page Scrolling Like a Pro ๐Ÿ“œ โ€‹

Smart scrolling management - Create seamless navigation experiences with precise scroll control!

๐ŸŽฏ Overview โ€‹

Scroll behavior configuration allows you to control how the page scrolls during navigation. Vue Router provides flexible options to customize scrolling behavior, from simple position restoration to complex scroll animations.

๐Ÿ“‹ Key Features โ€‹

  • Scroll Restoration: Automatically restore scroll position on back/forward navigation
  • Custom Scroll Targets: Scroll to specific elements or positions
  • Smooth Scrolling: Implement animated scroll transitions
  • Conditional Scrolling: Control scrolling based on route changes

๐Ÿ’ก When to Configure Scroll Behavior โ€‹

๐Ÿš€ Enhanced User Experience โ€‹

Single-Page Applications

  • Maintain scroll position during client-side navigation
  • Implement smooth transitions between pages
  • Handle anchor links and fragment navigation

Complex Layouts

  • Scroll to specific sections within pages
  • Handle fixed headers and navigation bars
  • Manage scroll in multi-column layouts

๐Ÿ”ง Technical Scenarios โ€‹

javascript
const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    // Custom scroll logic here
    if (savedPosition) {
      return savedPosition
    } else if (to.hash) {
      return { el: to.hash }
    } else {
      return { top: 0 }
    }
  }
})

๐Ÿš€ Basic Configuration โ€‹

Default Scroll Behavior โ€‹

Vue Router's default behavior restores scroll position for back/forward navigation:

javascript
const router = createRouter({
  history: createWebHistory(),
  routes: [...],
  scrollBehavior(to, from, savedPosition) {
    // Default behavior: restore position if available, else scroll to top
    if (savedPosition) {
      return savedPosition
    }
    return { top: 0 }
  }
})

Scroll to Top on Navigation โ€‹

Simple configuration to always scroll to top:

javascript
scrollBehavior(to, from, savedPosition) {
  // Always scroll to top on navigation
  return { top: 0 }
}

๐Ÿ”ง Advanced Techniques โ€‹

Example 1: Smart Scroll Restoration โ€‹

javascript
scrollBehavior(to, from, savedPosition) {
  // If it's a back/forward navigation, restore position
  if (savedPosition) {
    return savedPosition
  }
  
  // If route has hash, scroll to element
  if (to.hash) {
    return {
      el: to.hash,
      behavior: 'smooth', // Smooth scrolling
      top: 20 // Offset for fixed header
    }
  }
  
  // For new navigations, check if we should scroll to top
  if (to.path !== from.path) {
    return { top: 0 }
  }
  
  // Otherwise, maintain current position
  return false
}

Example 2: Route-Based Scroll Behavior โ€‹

javascript
scrollBehavior(to, from, savedPosition) {
  // Route-specific scroll behavior
  const scrollConfig = {
    // Default: scroll to top for new pages
    default: { top: 0 },
    
    // List pages: maintain scroll position
    '/products': savedPosition || { top: 0 },
    '/blog': savedPosition || { top: 0 },
    
    // Detail pages: always start from top
    '/products/:id': { top: 0 },
    '/blog/:slug': { top: 0 },
    
    // Admin area: different behavior
    '/admin': { top: 0, behavior: 'instant' }
  }
  
  // Get configuration for current route
  let config = scrollConfig.default
  
  // Check for exact matches first
  if (scrollConfig[to.path]) {
    config = scrollConfig[to.path]
  } else {
    // Check for pattern matches
    for (const pattern in scrollConfig) {
      if (pattern.includes(':') && pathToRegexp(pattern).test(to.path)) {
        config = scrollConfig[pattern]
        break
      }
    }
  }
  
  return config
}

๐Ÿ› ๏ธ Practical Examples โ€‹

Example 1: E-commerce Site Scroll Behavior โ€‹

javascript
scrollBehavior(to, from, savedPosition) {
  // Product listing - maintain scroll position
  if (to.path === '/products' && from.path === '/products') {
    // User is filtering/searching within products
    return savedPosition || { top: 0 }
  }
  
  // Product detail - always start from top
  if (to.path.startsWith('/products/') && to.params.id) {
    return { top: 0, behavior: 'smooth' }
  }
  
  // Checkout process - no scrolling between steps
  if (to.path.startsWith('/checkout') && from.path.startsWith('/checkout')) {
    return false
  }
  
  // Back to product list from detail - try to restore position
  if (from.path.startsWith('/products/') && to.path === '/products') {
    return savedPosition || { top: 0 }
  }
  
  // Default: smooth scroll to top for page changes
  if (to.path !== from.path) {
    return { top: 0, behavior: 'smooth' }
  }
  
  return false
}
javascript
scrollBehavior(to, from, savedPosition) {
  // Handle anchor links in documentation
  if (to.hash) {
    return {
      el: to.hash,
      behavior: 'smooth',
      top: 80 // Offset for fixed header
    }
  }
  
  // Between documentation pages, maintain reading position if possible
  if (to.path.startsWith('/docs') && from.path.startsWith('/docs')) {
    if (savedPosition) {
      return savedPosition
    }
    
    // Try to find the main content area
    const contentEl = document.querySelector('.content-main')
    if (contentEl) {
      return { el: contentEl, top: 0 }
    }
  }
  
  // Default behavior
  return savedPosition || { top: 0 }
}

๐Ÿ” Scroll Behavior Options โ€‹

Available Configuration Properties โ€‹

javascript
// Complete scroll configuration
{
  el: '#target-element',      // Scroll to specific element
  top: 100,                   // Scroll to specific position (pixels)
  left: 0,                    // Horizontal scroll position
  behavior: 'smooth',          // Scroll behavior: 'auto' or 'smooth'
  offset: { top: 50 }         // Additional offset
}

// Return false to prevent scrolling
return false

// Return a Promise for async operations
return new Promise(resolve => {
  setTimeout(() => {
    resolve({ top: 0 })
  }, 500)
})

Advanced Element Targeting โ€‹

javascript
scrollBehavior(to, from, savedPosition) {
  if (to.hash) {
    return {
      el: to.hash,
      // Account for fixed header
      top: document.querySelector('header')?.offsetHeight || 0,
      behavior: 'smooth'
    }
  }
  
  // Scroll to specific element based on route meta
  if (to.meta.scrollTo) {
    const targetEl = document.querySelector(to.meta.scrollTo)
    if (targetEl) {
      return {
        el: targetEl,
        behavior: 'smooth',
        top: 20
      }
    }
  }
  
  return savedPosition || { top: 0 }
}

๐Ÿš€ Performance Considerations โ€‹

Debounced Scrolling โ€‹

javascript
let scrollTimeout

scrollBehavior(to, from, savedPosition) {
  // Clear any pending scroll operations
  clearTimeout(scrollTimeout)
  
  return new Promise(resolve => {
    scrollTimeout = setTimeout(() => {
      if (savedPosition) {
        resolve(savedPosition)
      } else if (to.hash) {
        resolve({ el: to.hash, behavior: 'smooth' })
      } else {
        resolve({ top: 0 })
      }
    }, 100) // Small delay to ensure DOM is ready
  })
}

Conditional Smooth Scrolling โ€‹

javascript
scrollBehavior(to, from, savedPosition) {
  // Only use smooth scrolling for certain conditions
  const useSmoothScrolling = 
    !to.meta?.instantScroll &&
    !from.meta?.instantScroll &&
    window.matchMedia('(prefers-reduced-motion: no-preference)').matches
  
  const behavior = useSmoothScrolling ? 'smooth' : 'auto'
  
  if (savedPosition) {
    return { ...savedPosition, behavior }
  }
  
  if (to.hash) {
    return { el: to.hash, behavior }
  }
  
  return { top: 0, behavior }
}

๐ŸŽฏ Best Practices โ€‹

โœ… Do โ€‹

  • Respect User Preferences: Check prefers-reduced-motion
  • Handle Edge Cases: Account for element existence
  • Use Appropriate Offsets: Consider fixed headers and navigation
  • Test Thoroughly: Test on different devices and browsers

โŒ Don't โ€‹

  • Overuse Smooth Scrolling: Can be disorienting if overused
  • Ignore Performance: Avoid complex calculations during navigation
  • Forget Mobile: Test touch scrolling behavior
  • Skip Error Handling: Handle missing elements gracefully
  • Route Meta Fields: Store scroll configuration in route meta
  • Navigation Guards: Combine with scroll behavior for complex logic
  • Transition Components: Coordinate with page transitions
  • Browser History API: Understand underlying browser behavior

๐Ÿ’ก Pro Tip

Combine scroll behavior with Vue's Intersection Observer API to create sophisticated scroll-based animations and lazy loading that work seamlessly with your routing!

Ready to master scroll control? Start implementing intelligent scroll behavior to create polished, professional navigation experiences! ๐Ÿ“œ

๐Ÿš€ Vue Router - ่ฎฉๅ‰็ซฏ่ทฏ็”ฑๅ˜ๅพ—็ฎ€ๅ•่€Œๅผบๅคง | ๆž„ๅปบ็ŽฐไปฃๅŒ–ๅ•้กตๅบ”็”จ็š„ๆœ€ไฝณ้€‰ๆ‹ฉ