Scroll Behavior - Smooth Scrolling

What You'll Learn

  • Enable smooth scrolling with scroll-behavior: smooth
  • Control scroll offset with scroll-padding for fixed headers
  • Add margins around scroll targets with scroll-margin
  • Create accessible skip links for keyboard navigation
  • Respect user preferences with prefers-reduced-motion
  • Implement back-to-top buttons with smooth scrolling
  • Understand the difference between scroll-padding and scroll-margin

Introduction to Scroll Behavior

The scroll-behavior property controls how the browser scrolls when navigating to anchor links. Instead of instant jumps, you can create smooth, animated scrolling transitions - all with CSS, no JavaScript required.

Smooth scrolling improves user experience by providing visual continuity when navigating between page sections. It's particularly useful for single-page websites, table of contents navigation, and "back to top" buttons.

scroll-behavior Property

Apply smooth scrolling to the entire page or specific scroll containers. The property accepts two values: auto (default instant jump) and smooth (animated transition).

/* Enable smooth scrolling for entire page */ html { scroll-behavior: smooth; } /* Smooth scrolling for specific container */ .scroll-container { scroll-behavior: smooth; overflow-y: auto; } /* Disable smooth scrolling (instant jump) */ .instant-scroll { scroll-behavior: auto; /* Default */ }

scroll-padding: Offset for Fixed Headers

When you have fixed headers or sticky navigation, scrolling to anchors can position content behind these elements. scroll-padding adds an offset to prevent this issue.

/* Add padding offset for fixed headers */ html { scroll-behavior: smooth; scroll-padding-top: 80px; /* Height of fixed header */ } /* Different offsets for different sides */ .scroll-container { scroll-padding-top: 100px; /* Top offset */ scroll-padding-bottom: 50px; /* Bottom offset */ scroll-padding-left: 20px; /* Left offset (rare) */ scroll-padding-right: 20px; /* Right offset (rare) */ } /* Shorthand notation */ html { scroll-padding: 100px 20px 50px 20px; /* top right bottom left */ scroll-padding: 80px; /* All sides */ scroll-padding: 80px 0; /* Vertical only */ }

scroll-margin: Margin Around Targets

While scroll-padding is applied to the scroll container, scroll-margin is applied to individual scroll target elements. It creates space around the element when scrolled into view.

/* Add margin around scroll target */ section { scroll-margin-top: 100px; /* Space above when scrolled to */ scroll-margin-bottom: 20px; /* Space below */ } /* Shorthand */ section { scroll-margin: 100px 0 20px 0; /* top right bottom left */ scroll-margin: 100px 0; /* Vertical only */ } /* Use with :target for visual feedback */ section:target { scroll-margin-top: 100px; outline: 2px solid #6366f1; outline-offset: 8px; }

Difference: scroll-padding vs scroll-margin

/* scroll-padding: Applied to CONTAINER */ .scroll-container { scroll-padding-top: 100px; /* Affects all children when they scroll into view */ } /* scroll-margin: Applied to TARGET ELEMENT */ .scroll-target { scroll-margin-top: 100px; /* Only affects this specific element */ } /* Both achieve similar results but: - Use scroll-padding for global offset (fixed headers) - Use scroll-margin for per-element adjustments - scroll-margin overrides scroll-padding if both are set */

Skip to Content Links

Skip links improve accessibility by allowing keyboard users to bypass repetitive navigation. Combined with smooth scrolling, they create a polished, accessible experience.

<a href="#main-content" class="skip-link">Skip to main content</a> <nav> <!-- Navigation menu --> </nav> <main id="main-content"> <!-- Main content --> </main> /* Hidden skip link that appears on focus */ .skip-link { position: absolute; top: -40px; /* Hidden off-screen */ left: 0; background: #1f2937; color: white; padding: 0.5rem 1rem; text-decoration: none; border-radius: 0 0 4px 0; transition: top 0.3s ease; z-index: 9999; } .skip-link:focus { top: 0; /* Slides in when focused (Tab key) */ }

Respecting User Preferences

Some users experience vestibular disorders or motion sensitivity. Always respect the prefers-reduced-motion media query to disable animations for these users.

/* Enable smooth scrolling by default */ html { scroll-behavior: smooth; } /* Disable for users who prefer reduced motion */ @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; /* Instant scrolling */ } /* Also disable other animations */ *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } }

Back to Top Buttons

Combine smooth scrolling with "back to top" buttons for better navigation on long pages.

<a href="#top" class="back-to-top">↑ Back to Top</a> .back-to-top { position: fixed; bottom: 2rem; right: 2rem; padding: 1rem 1.5rem; background: #6366f1; color: white; text-decoration: none; border-radius: 50px; font-weight: 600; box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3); transition: all 0.3s ease; z-index: 100; } .back-to-top:hover { background: #4f46e5; transform: translateY(-4px); box-shadow: 0 6px 16px rgba(99, 102, 241, 0.4); } /* Show/hide based on scroll position (requires JS) */ .back-to-top.hidden { opacity: 0; pointer-events: none; }

Table of Contents Navigation

Smooth scrolling is perfect for table of contents or sidebar navigation linking to page sections.

<nav class="toc"> <h3>Table of Contents</h3> <ul> <li><a href="#section1">Introduction</a></li> <li><a href="#section2">Getting Started</a></li> <li><a href="#section3">Advanced Topics</a></li> </ul> </nav> <section id="section1">...</section> <section id="section2">...</section> <section id="section3">...</section> /* Smooth scrolling */ html { scroll-behavior: smooth; scroll-padding-top: 80px; /* For fixed header */ } /* Visual feedback for current section */ section:target { animation: highlight 2s ease; } @keyframes highlight { 0%, 100% { background: transparent; } 50% { background: rgba(99, 102, 241, 0.1); } }

Programmatic Scrolling

CSS scroll-behavior also affects JavaScript scrolling methods, providing consistency across all scroll interactions.

// Scroll to element (respects scroll-behavior CSS) document.getElementById('section').scrollIntoView(); // Scroll to element with options document.getElementById('section').scrollIntoView({ behavior: 'smooth', // Override CSS setting block: 'start', // Align to top inline: 'nearest' }); // Scroll to specific position window.scrollTo({ top: 0, behavior: 'smooth' // Override CSS setting }); // Smooth scroll by amount window.scrollBy({ top: 100, behavior: 'smooth' });

Key Takeaways