Understand Before You Build

  • HTML
    • Form
    • HTML pattern Attribute
  • CSS
    • inset
    • scroll-snap-type
    • margin-inline
    • Content-visibility
    • Scroll-Driven Animations
    • Isolation
    • @Container
    • @layer
    • :not()
    • :is()
    • :Where()
    • :has()
    • :target
    • backdrop-filter
    • :root
    • Color-scheme
    • Animations
    • Selectors
    • Object-fit
    • Logical Pseudo-Classes
    • :scope
    • Properties
    • Performance
    • Aspect-ratio
    • State Pseudo-Classes
    • Positioning
    • Resize
    • Structural Pseudo-Classes
    • Responsive Design
    • Units
    • Root & Scope Selectors
    • Scrolling
    • At-Rules
    • Target & URL Selectors
    • Spacing
    • Functions
    • Attribute Selectors
    • Layouts
    • Basic Selectors
    • Filters & Effects
    • Colors & Typography
    • Flexbox
    • Combinator Selectors
    • Grid
    • Form & UI State Selectors
    • AI CSS Generator
  • Sass
    • Variables
    • Nesting
    • Mixins
    • Reusable styles
    • Large project management
  • CSS Frameworks
    • Material UI
    • Bootstrap
    • Tailwind CSS
  • React UI
    • Performance Optimization
    • React.memo
    • useMemo
    • useCallback
    • Lazy Loading
    • Code Splitting
    • Virtual DOM Optimization
    • Preventing Re-renders
    • Props & State
    • Hooks
    • Component-based architecture
    • State-driven UI updates
  • Figma
    • Design systems
    • Tokens
    • Variables
    • Auto layout
    • Component variants
    • Design handoff
    • UI consistency

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"]
Section 1
Section 2
Section 3
[/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.