CSS Scroll Snap: Creating Smooth Scrolling Experiences
What is CSS Scroll Snap?
CSS Scroll Snap gives you control over the scroll position after a user finishes scrolling. Instead of landing at an arbitrary position, the scroll will snap to specific points you define. This creates smooth, precise scrolling experiences without JavaScript.
Basic Scroll Snap Setup
Scroll snap requires two things:
- A scroll container with snap rules
- Snap targets (child elements) that define snap points
/* The scroll container */
.container {
scroll-snap-type: y mandatory;
overflow-y: scroll;
height: 100vh;
}
/* The snap targets */
.section {
scroll-snap-align: start;
height: 100vh;
}scroll-snap-type
Defines the snap direction and strictness on the scroll container:
/* Vertical snapping */
.container { scroll-snap-type: y mandatory; }
/* Horizontal snapping */
.container { scroll-snap-type: x mandatory; }
/* Both directions */
.container { scroll-snap-type: both mandatory; }mandatory vs proximity
/* mandatory: ALWAYS snaps to a snap point after scrolling */
scroll-snap-type: y mandatory;
/* proximity: Only snaps when close to a snap point */
scroll-snap-type: y proximity;- mandatory: Use when every section must be fully visible (full-page scroll)
- proximity: Use for a gentler snap that only activates when near a target (image galleries)
scroll-snap-align
Defines which part of the child element aligns with the scroll container:
.item { scroll-snap-align: start; } /* Top/left of item aligns */
.item { scroll-snap-align: center; } /* Center of item aligns */
.item { scroll-snap-align: end; } /* Bottom/right of item aligns */Practical Examples
Full-Page Scroll Sections
.page-container {
scroll-snap-type: y mandatory;
overflow-y: scroll;
height: 100vh;
}
.page-section {
scroll-snap-align: start;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.page-section:nth-child(1) { background: #3498db; }
.page-section:nth-child(2) { background: #2ecc71; }
.page-section:nth-child(3) { background: #e74c3c; }
.page-section:nth-child(4) { background: #f39c12; }Horizontal Image Gallery
.gallery {
display: flex;
overflow-x: scroll;
scroll-snap-type: x mandatory;
gap: 1rem;
padding: 1rem;
-webkit-overflow-scrolling: touch;
}
.gallery__item {
scroll-snap-align: center;
flex: 0 0 80%;
border-radius: 12px;
overflow: hidden;
}
.gallery__item img {
width: 100%;
height: 300px;
object-fit: cover;
}Card Carousel
.carousel {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
gap: 1.5rem;
padding: 1rem;
scroll-padding: 1rem;
}
.carousel::-webkit-scrollbar {
display: none;
}
.carousel__card {
scroll-snap-align: start;
flex: 0 0 300px;
background: white;
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}scroll-padding
Adds an offset so items don't snap directly to the edge. Useful when you have a fixed header:
.container {
scroll-snap-type: y mandatory;
overflow-y: scroll;
scroll-padding-top: 80px; /* Account for fixed header */
}/* All sides */
scroll-padding: 1rem;
/* Individual sides */
scroll-padding-top: 80px;
scroll-padding-inline: 1rem;scroll-margin
Adds an offset on the snap target side (the child):
.section {
scroll-snap-align: start;
scroll-margin-top: 80px; /* Offset from top when snapping */
}scroll-snap-stop
Controls whether a fast scroll can skip snap points:
/* normal: fast scrolling can skip past snap points (default) */
.item { scroll-snap-stop: normal; }
/* always: must stop at every snap point */
.item { scroll-snap-stop: always; }Use always for important content that should never be skipped.
Hiding Scrollbar
For a cleaner look, you can hide the scrollbar while keeping scroll functionality:
.carousel {
overflow-x: auto;
scrollbar-width: none; /* Firefox */
}
.carousel::-webkit-scrollbar {
display: none; /* Chrome, Safari */
}Vertical Snap with Variable Heights
.scroll-container {
scroll-snap-type: y proximity;
overflow-y: scroll;
height: 100vh;
}
.content-section {
scroll-snap-align: start;
min-height: 50vh;
padding: 3rem 2rem;
}Using proximity instead of mandatory works better when sections have variable heights.
Accessibility Considerations
- Always ensure users can still scroll freely with keyboard and assistive devices
- Use proximity over mandatory when sections have varying content lengths
- Add scroll-padding to account for fixed navigation
- Test with keyboard navigation (Tab, arrow keys)
Summary
CSS Scroll Snap creates polished scrolling experiences purely with CSS. Use scroll-snap-type on the container for direction and strictness, scroll-snap-align on children for alignment, scroll-padding for fixed header offsets, and scroll-snap-stop: always for must-see content. It is perfect for full-page scrolling, image carousels, card galleries, and any horizontal or vertical scroll-based navigation.