--- description: Scroll behavior and navigation patterns alwaysApply: false globs: **/*.{ts,tsx,js,jsx,vue,css,scss} --- # Scroll & Navigation Patterns ## Scroll Philosophy **Default to Natural Scrolling** Natural, uncontrolled scrolling should be your default. Only implement controlled scroll behaviors when they serve a clear purpose. ### When to Control Scroll - ✅ Full-page sections (snap scrolling) - ONLY for portfolios/showcases - ✅ Carousels and galleries - ✅ Onboarding flows - ✅ Modal/overlay open states ### When to Allow Natural Scroll (Most Cases) - ✅ Long-form content - ✅ Blog posts and articles - ✅ List views - ✅ Traditional navigation - ✅ E-commerce sites - ✅ Documentation - ✅ Applications and dashboards ## Snap Scrolling (Use Sparingly) **⚠️ CAVEAT**: Snap scrolling is NOT always appropriate. Use only for specific cases like portfolios and presentations. ```css /* Container with snap behavior */ html { scroll-snap-type: y mandatory; scroll-padding-top: 4rem; } .snap-section { scroll-snap-align: start; scroll-snap-stop: always; min-height: 100vh; min-height: 100dvh; } ``` ## Smooth Scrolling ```css html { scroll-behavior: smooth; } /* Respect user preferences */ @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } } ``` ## Scroll Lock (Modal Open) ```javascript const lockScroll = () => { const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth; document.body.style.overflow = 'hidden'; document.body.style.paddingRight = `${scrollbarWidth}px`; }; const unlockScroll = () => { document.body.style.overflow = ''; document.body.style.paddingRight = ''; }; ``` ## Scroll Position Persistence ```javascript // Save before navigation const saveScrollPosition = () => { sessionStorage.setItem('scrollPosition', window.scrollY.toString()); }; // Restore on page load const restoreScrollPosition = () => { const savedPosition = sessionStorage.getItem('scrollPosition'); if (savedPosition) { window.scrollTo(0, parseInt(savedPosition, 10)); sessionStorage.removeItem('scrollPosition'); } }; ``` ## Overscroll Behavior ```css /* Disable bounce on body */ body { overscroll-behavior: none; } /* Contain overscroll to element */ .modal { overscroll-behavior: contain; } ```