scroll-snap-type
The scroll-snap-type property is part of the CSS Scroll Snap Module.
It allows developers to create smooth, controlled scrolling experiences where content automatically “snaps” into position while scrolling.
This feature is commonly used for:
- Fullscreen section scrolling
- Image sliders and carousels
- Vertical app-like layouts
- Story-style mobile interfaces
- Horizontal product showcases
- Presentation-style websites
|
Class
|
Styles
|
snap-none
|
scroll-snap-type: none;
|
snap-x
|
scroll-snap-type: x var(--tw-scroll-snap-strictness);
|
snap-y
|
scroll-snap-type: y var(--tw-scroll-snap-strictness);
|
snap-both
|
scroll-snap-type: both var(--tw-scroll-snap-strictness);
|
snap-mandatory
|
--tw-scroll-snap-strictness: mandatory;
|
snap-proximity
|
--tw-scroll-snap-strictness: proximity;
|
When using:
[code theme="dark"]
scroll-snap-type: y mandatory;
[/code]
it means:
- y → snapping works vertically
- mandatory → browser must stop at a snap point
Basic Example
[code theme="dark"]
.container{
height:100vh;
overflow-y:scroll;
scroll-snap-type:y mandatory;
}
.section{
height:100vh;
scroll-snap-align:start;
}
[/code]
In this example:
- The container becomes vertically scrollable
- Each section takes full screen height
- Scrolling automatically snaps to the next section
HTML Structure
[code theme="dark"]
[/code]
How It Works
The parent container controls the snapping behavior using:
[code theme="dark"]
scroll-snap-type
[/code]
The child elements define where snapping should happen using:
[code theme="dark"]
scroll-snap-align
[/code]
scroll-snap-align Values
- start → snaps to top/start edge
- center → snaps to center
- end → snaps to bottom/end edge
Mandatory vs Proximity
There are two major snapping behaviors:
1. mandatory
[code theme="dark"]
scroll-snap-type:y mandatory;
[/code]
- Browser always snaps strictly
- More controlled experience
- Best for fullscreen sections
2. proximity
[code theme="dark"]
scroll-snap-type:y proximity;
[/code]
- Snaps only when scroll position is near a snap point
- Feels more natural
- Better for normal content layouts
Horizontal Scroll Snap
For horizontal sliders:
[code theme="dark"]
scroll-snap-type:x mandatory;
[/code]
Both Directions
[code theme="dark"]
scroll-snap-type:both mandatory;
[/code]
Useful for:
- Interactive maps
- 2D scrolling interfaces
- Advanced galleries
Image Slider Example
[preview data="eyJodG1sIjoiPGZpZ3VyZSBjbGFzcz1cImZsZXggZmxleC1jb2wgZ2FwLTEgcm91bmRlZC14bCBiZy1ncmF5LTk1MC81IHAtMSBpbnNldC1yaW5nIGluc2V0LXJpbmctZ3JheS05NTAvNSBkYXJrOmJnLXdoaXRlLzEwIGRhcms6aW5zZXQtcmluZy13aGl0ZS8xMFwiPjxkaXYgY2xhc3M9XCJub3QtcHJvc2Ugb3ZlcmZsb3ctYXV0byByb3VuZGVkLWxnIGJnLXdoaXRlIG91dGxpbmUgb3V0bGluZS13aGl0ZS81IGRhcms6YmctZ3JheS05NTAvNTBcIj48ZGl2IGNsYXNzPVwicmVsYXRpdmVcIj48ZGl2IGNsYXNzPVwibWItNiBtbC1bNTAlXSBmbGV4IGl0ZW1zLWVuZCBqdXN0aWZ5LXN0YXJ0IHB0LTEwXCI+PGRpdiBjbGFzcz1cImRhcms6aGlnaGxpZ2h0LXdoaXRlLzEwIG1sLTIgcm91bmRlZCBiZy1pbmRpZ28tNTAgcHgtMS41IGZvbnQtbW9ubyB0ZXh0LVswLjYyNXJlbV0gbGVhZGluZy02IHRleHQtaW5kaWdvLTYwMCByaW5nLTEgcmluZy1pbmRpZ28tNjAwIHJpbmctaW5zZXQgZGFyazpiZy1pbmRpZ28tNTAwIGRhcms6dGV4dC13aGl0ZSBkYXJrOnJpbmctMFwiPnNuYXAgcG9pbnQ8L2Rpdj48ZGl2IGNsYXNzPVwiYWJzb2x1dGUgdG9wLTAgYm90dG9tLTAgbGVmdC0xLzIgYm9yZGVyLWwgYm9yZGVyLWluZGlnby01MDBcIj48L2Rpdj48L2Rpdj48ZGl2IGNsYXNzPVwicmVsYXRpdmUgZmxleCB3LWZ1bGwgc25hcC14IHNuYXAtbWFuZGF0b3J5IGdhcC02IG92ZXJmbG93LXgtYXV0byBwYi0xNFwiPjxkaXYgY2xhc3M9XCJzaHJpbmstMCBzbmFwLWNlbnRlclwiPjxkaXYgY2xhc3M9XCJ3LTQgc2hyaW5rLTAgc206dy0zN1wiPjwvZGl2PjwvZGl2PjxkaXYgY2xhc3M9XCJzaHJpbmstMCBzbmFwLWNlbnRlciBmaXJzdDpwbC04IGxhc3Q6cHItOFwiPjxpbWcgY2xhc3M9XCJoLTQwIHctODAgc2hyaW5rLTAgcm91bmRlZC1sZyBiZy13aGl0ZVwiIHNyYz1cImh0dHBzOi8vaW1hZ2VzLnVuc3BsYXNoLmNvbS9waG90by0xNjA0OTk5NTY1OTc2LTg5MTNhZDJkZGI3Yz9peGxpYj1yYi0xLjIuMSZhbXA7aXhpZD1Nbnd4TWpBM2ZEQjhNSHh3YUc5MGJ5MXdZV2RsZkh4OGZHVnVmREI4Zkh4OCZhbXA7YXV0bz1mb3JtYXQmYW1wO2ZpdD1jcm9wJmFtcDt3PTMyMCZhbXA7aD0xNjAmYW1wO3E9ODBcIj48L2Rpdj48ZGl2IGNsYXNzPVwic2hyaW5rLTAgc25hcC1jZW50ZXIgZmlyc3Q6cGwtOCBsYXN0OnByLThcIj48aW1nIGNsYXNzPVwiaC00MCB3LTgwIHNocmluay0wIHJvdW5kZWQtbGcgYmctd2hpdGVcIiBzcmM9XCJodHRwczovL2ltYWdlcy51bnNwbGFzaC5jb20vcGhvdG8tMTU0MDIwNjM1MS1kNjQ2NWIzYWM1YzE/aXhsaWI9cmItMS4yLjEmYW1wO2l4aWQ9TW53eE1qQTNmREI4TUh4d2FHOTBieTF3WVdkbGZIeDhmR1Z1ZkRCOGZIeDgmYW1wO2F1dG89Zm9ybWF0JmFtcDtmaXQ9Y3JvcCZhbXA7dz0zMjAmYW1wO2g9MTYwJmFtcDtxPTgwXCI+PC9kaXY+PGRpdiBjbGFzcz1cInNocmluay0wIHNuYXAtY2VudGVyIGZpcnN0OnBsLTggbGFzdDpwci04XCI+PGltZyBjbGFzcz1cImgtNDAgdy04MCBzaHJpbmstMCByb3VuZGVkLWxnIGJnLXdoaXRlXCIgc3JjPVwiaHR0cHM6Ly9pbWFnZXMudW5zcGxhc2guY29tL3Bob3RvLTE2MjI4OTA4MDYxNjYtMTExZDdmNmM3Yzk3P2l4bGliPXJiLTEuMi4xJmFtcDtpeGlkPU1ud3hNakEzZkRCOE1IeHdhRzkwYnkxd1lXZGxmSHg4ZkdWdWZEQjhmSHg4JmFtcDthdXRvPWZvcm1hdCZhbXA7Zml0PWNyb3AmYW1wO3c9MzIwJmFtcDtoPTE2MCZhbXA7cT04MFwiPjwvZGl2PjxkaXYgY2xhc3M9XCJzaHJpbmstMCBzbmFwLWNlbnRlciBmaXJzdDpwbC04IGxhc3Q6cHItOFwiPjxpbWcgY2xhc3M9XCJoLTQwIHctODAgc2hyaW5rLTAgcm91bmRlZC1sZyBiZy13aGl0ZVwiIHNyYz1cImh0dHBzOi8vaW1hZ2VzLnVuc3BsYXNoLmNvbS9waG90by0xNTkwNTIzMjc3NTQzLWE5NGQyZTRlYjAwYj9peGxpYj1yYi0xLjIuMSZhbXA7aXhpZD1Nbnd4TWpBM2ZEQjhNSHh3YUc5MGJ5MXdZV2RsZkh4OGZHVnVmREI4Zkh4OCZhbXA7YXV0bz1mb3JtYXQmYW1wO2ZpdD1jcm9wJmFtcDt3PTMyMCZhbXA7aD0xNjAmYW1wO3E9ODBcIj48L2Rpdj48ZGl2IGNsYXNzPVwic2hyaW5rLTAgc25hcC1jZW50ZXIgZmlyc3Q6cGwtOCBsYXN0OnByLThcIj48aW1nIGNsYXNzPVwiaC00MCB3LTgwIHNocmluay0wIHJvdW5kZWQtbGcgYmctd2hpdGVcIiBzcmM9XCJodHRwczovL2ltYWdlcy51bnNwbGFzaC5jb20vcGhvdG8tMTU3NTQyNDkwOTEzOC00NmIwNWU1OTE5ZWM/aXhsaWI9cmItMS4yLjEmYW1wO2l4aWQ9TW53eE1qQTNmREI4TUh4d2FHOTBieTF3WVdkbGZIeDhmR1Z1ZkRCOGZIeDgmYW1wO2F1dG89Zm9ybWF0JmFtcDtmaXQ9Y3JvcCZhbXA7dz0zMjAmYW1wO2g9MTYwJmFtcDtxPTgwXCI+PC9kaXY+PGRpdiBjbGFzcz1cInNocmluay0wIHNuYXAtY2VudGVyIGZpcnN0OnBsLTggbGFzdDpwci04XCI+PGltZyBjbGFzcz1cImgtNDAgdy04MCBzaHJpbmstMCByb3VuZGVkLWxnIGJnLXdoaXRlXCIgc3JjPVwiaHR0cHM6Ly9pbWFnZXMudW5zcGxhc2guY29tL3Bob3RvLTE1NTkzMzMwODYtYjBhNTYyMjVhOTNjP2l4bGliPXJiLTEuMi4xJmFtcDtpeGlkPU1ud3hNakEzZkRCOE1IeHdhRzkwYnkxd1lXZGxmSHg4ZkdWdWZEQjhmSHg4JmFtcDthdXRvPWZvcm1hdCZhbXA7Zml0PWNyb3AmYW1wO3c9MzIwJmFtcDtoPTE2MCZhbXA7cT04MFwiPjwvZGl2PjxkaXYgY2xhc3M9XCJzaHJpbmstMCBzbmFwLWNlbnRlclwiPjxkaXYgY2xhc3M9XCJ3LTQgc2hyaW5rLTAgc206dy0zN1wiPjwvZGl2PjwvZGl2PjwvZGl2PjwvZGl2PjwvZGl2PjwvZmlndXJlPiIsImNzcyI6Ii5teS1idG4ge1xuICBwYWRkaW5nOiAxMHB4IDIwcHg7XG4gIGJhY2tncm91bmQ6ICMxMGI5ODE7XG4gIGNvbG9yOiB3aGl0ZTtcbiAgYm9yZGVyOiBub25lO1xuICBib3JkZXItcmFkaXVzOiA4cHg7XG4gIGN1cnNvcjogcG9pbnRlcjtcbn0iLCJqcyI6ImRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIubXktYnRuXCIpLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoKSA9PiB7XG4gIGFsZXJ0KFwiSGVsbG8gZnJvbSBMaXZlIFByZXZpZXchXCIpO1xufSk7In0="]
[code theme="dark"]
.slider{
display:flex;
overflow-x:auto;
scroll-snap-type:x mandatory;
}
.slide{
min-width:100%;
scroll-snap-align:center;
}
[/code]
Useful Related Properties
scroll-padding
Adds spacing for snapping position.
Useful when fixed headers exist.
[code theme="dark"]
.container{
scroll-padding-top:80px;
}
[/code]
scroll-margin
Adds margin around snap elements.
[code theme="dark"]
.section{
scroll-margin-top:20px;
}
[/code]
scroll-behavior
Makes snapping smoother.
[code theme="dark"]
html{
scroll-behavior:smooth;
}
[/code]
Advantages
- Creates app-like smooth experiences
- Improves mobile interaction
- Works without JavaScript
- Better performance than JS scroll libraries
- Easy to implement
- Modern browser optimized
Disadvantages
- Can feel restrictive with mandatory snapping
- Not ideal for long reading content
- May create usability issues if overused
- Nested scroll snapping can become complex
Cross Browser Compatibility
- Chrome → Fully Supported
- Edge → Fully Supported
- Firefox → Fully Supported
- Safari → Supported
- Mobile Browsers → Good Support
Older browsers had partial support for early versions of CSS Scroll Snap, but modern browsers now support the standardized syntax well.
For best compatibility:
- Use modern syntax only
- Test on Safari for touch scrolling behavior
- Avoid overly aggressive mandatory snapping on mobile devices
Browser Support Summary
[code theme="dark"]
scroll-snap-type:y mandatory;
[/code]
is considered a modern CSS feature with excellent support across all major modern browsers.