JavaScript Element scrollsnapchange Event

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Experimental
Instance event

What You’ll Learn

The scrollsnapchange event fires on a scroll container when scrolling ends and a new scroll snap target is selected—just before scrollend. Learn SnapEvent, snapTargetBlock / snapTargetInline, the CSS you need, and five try-it labs.

01

Kind

Instance event

02

Type

SnapEvent

03

When

New snap selected

04

Handler

onscrollsnapchange

05

Status

Experimental

06

Baseline

Limited availability

Introduction

CSS scroll snap lets a scroller “stick” to child items (carousels, full-page sections, card rails). scrollsnapchange is the JavaScript signal that says: “Scrolling finished, and this child is now the selected snap target.”

It fires on the scroll container at the end of a gesture (touch, scrollbar drag, and similar), and only when a new snap target was chosen. MDN notes it runs just before the matching scrollend event.

💡
Beginner tip

Without CSS snap (scroll-snap-type on the container and scroll-snap-align on children), there is nothing to snap to—and this event will not help you. Style first, then listen.

Understanding scrollsnapchange

An instance event that answers: “Did scrolling end on a newly selected snap target?”

  • Trigger — scroll gesture finished and a new snap target was selected.
  • Event typeSnapEvent with axis target properties.
  • Timing — at end of scrolling, just before scrollend.
  • CSS required — scroll snap on the container and children.
  • Status — Experimental; Limited availability (not Baseline).

🎨 Scroll Snap Setup

Turn a box into a snap container and mark children as snap targets:

JavaScript
main {
  width: 250px;
  height: 450px;
  overflow: scroll;
  scroll-snap-type: block mandatory;
}

main > section {
  scroll-snap-align: start;
}
  • scroll-snap-type — axis + strictness (mandatory / proximity).
  • scroll-snap-align — where each child snaps (start, center, end).
  • Listen for scrollsnapchange on the same element that scrolls.

📝 Syntax

Use the event name with addEventListener, or set the handler property:

JavaScript
addEventListener("scrollsnapchange", (event) => { });

onscrollsnapchange = (event) => { };

Event type

A SnapEvent (inherits from Event).

SnapEvent properties

PropertyMeaning
snapTargetBlockNewly selected snap target on the block axis (or null)
snapTargetInlineNewly selected snap target on the inline axis (or null)

Feature detection

JavaScript
if ("onscrollsnapchange" in window) {
  el.addEventListener("scrollsnapchange", onSnap);
} else {
  // Fallback: IntersectionObserver or scrollend + geometry
}

⚡ Quick Reference

GoalCode / note
Listenel.addEventListener("scrollsnapchange", fn)
Handler propertyel.onscrollsnapchange = fn
Block targetevent.snapTargetBlock
Inline targetevent.snapTargetInline
CSSscroll-snap-type + scroll-snap-align
MDN statusExperimental · Limited availability

🔍 At a Glance

Four facts to remember about scrollsnapchange.

Event type
SnapEvent

snapTarget*

Means
new snap

At scroll end

Before
scrollend

When both fire

Status
experimental

Limited availability

Examples Gallery

Examples follow MDN Element: scrollsnapchange event. Use a Chromium browser for the try-it labs; scroll the snap panes until they settle.

📚 Getting Started

MDN listener patterns with snapTargetBlock.

Example 1 — Mark Selected Snap Target (MDN)

Add a selected class to the newly selected block-axis snap child.

JavaScript
const scrollingElem = document.querySelector("main");

scrollingElem.addEventListener("scrollsnapchange", (event) => {
  event.snapTargetBlock.classList.add("selected");
});
Try It Yourself

How It Works

After the gesture ends on a new snap target, snapTargetBlock points at that child so you can style or announce it.

Example 2 — onscrollsnapchange Property

Same idea using the handler property form.

JavaScript
const scrollingElem = document.querySelector("main");

scrollingElem.onscrollsnapchange = (event) => {
  const target = event.snapTargetBlock;
  if (target) {
    console.log("Snapped to:", target.dataset.label);
  }
};
Try It Yourself

How It Works

Prefer addEventListener when you need multiple listeners or easy removal.

📈 Detect, Highlight & Order

Feature-detect, manage selection UI, and see timing vs scrollend.

Example 3 — Feature Detect + Log Label

Check support, then log the snapped card label.

JavaScript
const box = document.getElementById("snap-box");
const out = document.getElementById("out");

if ("onscrollsnapchange" in window) {
  out.textContent = "scrollsnapchange supported — scroll to snap";
  box.addEventListener("scrollsnapchange", (event) => {
    const t = event.snapTargetBlock;
    out.textContent = t
      ? "snapped: " + (t.dataset.label || t.textContent.trim())
      : "snapped (no block target)";
  });
} else {
  out.textContent = "scrollsnapchange not supported in this browser";
}
Try It Yourself

How It Works

"onscrollsnapchange" in window is a simple support check before you rely on the event.

Example 4 — Exclusive Highlight

Clear previous selected classes, then mark only the new snap target.

JavaScript
const box = document.getElementById("snap-box");

box.addEventListener("scrollsnapchange", (event) => {
  box.querySelectorAll(".selected").forEach((el) => {
    el.classList.remove("selected");
  });
  if (event.snapTargetBlock) {
    event.snapTargetBlock.classList.add("selected");
  }
});
Try It Yourself

How It Works

Useful for carousels that should show exactly one active card after each settle.

Example 5 — Order vs scrollend

Log both events to see scrollsnapchange fire just before scrollend.

JavaScript
const box = document.getElementById("snap-box");
const out = document.getElementById("out");
const log = [];

function push(msg) {
  log.push(msg);
  out.textContent = log.slice(-6).join("\n");
}

box.addEventListener("scrollsnapchange", () => {
  push("1) scrollsnapchange");
});

box.addEventListener("scrollend", () => {
  push("2) scrollend");
});
Try It Yourself

How It Works

MDN: when a new snap target is selected, scrollsnapchange runs first, then scrollend.

🚀 Common Use Cases

  • Highlight the active carousel / story card after snap settles.
  • Update page dots or a progress label to match the snapped section.
  • Lazy-load or prefetch content for the newly selected slide.
  • Announce the active item for accessibility after snap.
  • Run analytics only when the user lands on a new snap target.

🔧 How It Works

1

CSS snap container

scroll-snap-type on the scroller; scroll-snap-align on children.

Setup
2

User scrolls

Gesture moves over potential snap targets (scrollsnapchanging may fire).

Gesture
3

Gesture ends

If a new snap target is selected, scrollsnapchange fires on the container.

Event
4

Then scrollend

Read snapTargetBlock / Inline, update UI, then scrollend may follow.

📝 Notes

  • MDN: Experimental + Limited availability — Experimental banner shown; not Deprecated / Non-standard.
  • Requires CSS scroll snap on the scrolling element and its children.
  • Fires only when a new snap target is selected at scroll end.
  • Chromium 129+ today; feature-detect for Firefox / Safari.
  • Related learning: scrollend, scroll, addEventListener(), JavaScript hub.

Limited Browser Availability

scrollsnapchange is Experimental and not Baseline on MDN. Logos use the shared browser-image-sprite.png sprite from this project. Expect Chromium-family support; Firefox and Safari generally lack this event.

Experimental · Limited availability

Element scrollsnapchange

Fires when a new scroll snap target is selected at scroll end. Chrome / Edge 129+, Opera 115+; feature-detect elsewhere.

Limited Not Baseline
Google Chrome 129+
Supported
Mozilla Firefox Not supported
Unavailable
Apple Safari Not supported
Unavailable
Microsoft Edge 129+
Supported
Opera 115+
Supported
Internet Explorer Not supported
Unavailable
scrollsnapchange Limited

Bottom line: Use CSS scroll snap first, listen on the container, read SnapEvent targets, and keep a fallback for browsers without the event.

Conclusion

scrollsnapchange tells you when a scroll snap container has settled on a new snap target. Pair CSS scroll snap with a SnapEvent listener, style snapTargetBlock / snapTargetInline, and feature-detect because support is still Limited / Experimental.

Continue with scrollsnapchanging, scrollend, addEventListener(), or the JavaScript hub.

💡 Best Practices

✅ Do

  • Set up CSS scroll snap before relying on the event
  • Listen on the scrolling container, not each child
  • Null-check snapTargetBlock / snapTargetInline
  • Feature-detect with "onscrollsnapchange" in window
  • Prefer addEventListener for multiple handlers

❌ Don’t

  • Ship to all browsers without a fallback plan
  • Confuse it with scrollsnapchanging (pending vs selected)
  • Expect it without scroll-snap-type / scroll-snap-align
  • Assume Firefox or Safari support yet
  • Overwrite onscrollsnapchange if you need multiple listeners

Key Takeaways

Knowledge Unlocked

Five things to remember about scrollsnapchange

New snap selected at scroll end—read SnapEvent, then style.

5
Core concepts
📄02

SnapEvent

snapTarget*

API
03

vs changing

pending vs final

Compare
🎨04

CSS first

snap-type + align

Setup
🎯05

Experimental

Chromium today

Status

❓ Frequently Asked Questions

It fires on a scroll container at the end of a scrolling operation when a new scroll snap target has been selected—just before the scrollend event.
MDN marks Element scrollsnapchange as Experimental and Limited availability (not Baseline). It is not Deprecated or Non-standard. Support is mainly Chromium-based today.
A SnapEvent, which inherits from Event. Use snapTargetBlock and snapTargetInline to read the newly selected snap targets on each axis.
When the user finishes scrolling in the container—for example after a touch gesture or after dragging the scrollbar—and releases the gesture.
scrollsnapchanging can fire during a gesture when a pending snap target changes. scrollsnapchange fires once at the end when the new snap target is actually selected.
Set scroll-snap-type on the scroll container and scroll-snap-align (often start or center) on child snap targets so the browser has something to snap to.
Did you know?

scrollsnapchanging can fire multiple times while the user is still scrolling over potential targets. scrollsnapchange fires once when the selection is final—better for dots, analytics, and “active card” styling.

Next: scrollsnapchanging

Preview the pending snap target while the user is still scrolling.

scrollsnapchanging →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful