JavaScript Element scrollsnapchanging Event

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

What You’ll Learn

The scrollsnapchanging event fires on a scroll container when a pending snap target changes during a gesture. Learn SnapEvent, how it differs from scrollsnapchange, CSS scroll snap setup, and five try-it labs.

01

Kind

Instance event

02

Type

SnapEvent

03

When

Pending snap changes

04

Handler

onscrollsnapchanging

05

Status

Experimental

06

Baseline

Limited availability

Introduction

While the user is still scrolling a snap container, the browser may decide which child would become the snap target if the gesture ended now. That child is the pending snap target. scrollsnapchanging reports it.

It fires during the gesture (touch drag, scrollbar drag, and similar), and can fire multiple times as the pending target changes. MDN notes it does not fire for every snap child you pass—only for the last target the snap would potentially rest on.

💡
Beginner tip

Think of scrollsnapchanging as a live preview (“about to land here”) and scrollsnapchange as the final selection after the gesture ends.

Understanding scrollsnapchanging

An instance event that answers: “Which snap target is currently pending during this gesture?”

  • Trigger — pending snap target changes while scrolling.
  • Event typeSnapEvent with axis target properties.
  • Timing — during the gesture (can fire multiple times).
  • Not every child — only the potential rest target, not each crossed one.
  • Status — Experimental; Limited availability (not Baseline).

🎨 Scroll Snap Setup

Same CSS foundation as other scroll snap events:

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

main > section {
  scroll-snap-align: start;
}
  • scroll-snap-type on the scrolling container.
  • scroll-snap-align on each snap child.
  • Listen for scrollsnapchanging on that same container.

📝 Syntax

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

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

onscrollsnapchanging = (event) => { };

Event type

A SnapEvent (inherits from Event).

SnapEvent properties

PropertyMeaning
snapTargetBlockPending snap target on the block axis (or null)
snapTargetInlinePending snap target on the inline axis (or null)

Feature detection

JavaScript
if ("onscrollsnapchanging" in window) {
  el.addEventListener("scrollsnapchanging", onPending);
} else {
  // Fallback: scroll + geometry / IntersectionObserver
}

⚡ Quick Reference

GoalCode / note
Listenel.addEventListener("scrollsnapchanging", fn)
Handler propertyel.onscrollsnapchanging = fn
Pending blockevent.snapTargetBlock
Pending inlineevent.snapTargetInline
Final selectionElement scrollsnapchange
MDN statusExperimental · Limited availability

🔍 At a Glance

Four facts to remember about scrollsnapchanging.

Event type
SnapEvent

snapTarget*

Means
pending

During gesture

Frequency
multi

Per gesture

Status
experimental

Limited availability

Examples Gallery

Examples follow MDN Element: scrollsnapchanging event. Use a Chromium browser; scroll slowly so pending targets update before you release.

📚 Getting Started

MDN “pending” class pattern with snapTargetBlock.

Example 1 — Mark Pending Snap Target (MDN)

Clear old pending classes, then mark the current pending child.

JavaScript
scrollingElem.addEventListener("scrollsnapchanging", (event) => {
  // remove previously-set "pending" classes
  const pendingElems = document.querySelectorAll(".pending");
  pendingElems.forEach((elem) => {
    elem.classList.remove("pending");
  });

  // Set current pending snap target class to "pending"
  event.snapTargetBlock.classList.add("pending");
});
Try It Yourself

How It Works

As the gesture updates the potential rest target, you restyle only that one child for a live preview.

Example 2 — onscrollsnapchanging Property

Log the pending card label using the handler property.

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

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

How It Works

Prefer addEventListener when you need multiple listeners or easy removal.

📈 Detect, Pair & Count

Feature-detect, combine with scrollsnapchange, and see how often it fires.

Example 3 — Feature Detect + Log Label

Check support, then show the pending card while scrolling.

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

if ("onscrollsnapchanging" in window) {
  out.textContent = "supported — scroll slowly";
  box.addEventListener("scrollsnapchanging", (event) => {
    const t = event.snapTargetBlock;
    out.textContent = t
      ? "pending: " + (t.dataset.label || t.textContent.trim())
      : "pending (no block target)";
  });
} else {
  out.textContent = "scrollsnapchanging not supported";
}
Try It Yourself

How It Works

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

Example 4 — Pending Preview + Selected Final

Use pending during the gesture and selected after scrollsnapchange.

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

box.addEventListener("scrollsnapchanging", (event) => {
  box.querySelectorAll(".pending").forEach((el) => el.classList.remove("pending"));
  if (event.snapTargetBlock) {
    event.snapTargetBlock.classList.add("pending");
  }
});

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

How It Works

Live preview during motion; commit styling only when the new snap target is selected.

Example 5 — Count scrollsnapchanging Fires

See how many pending updates happen before one scrollsnapchange.

JavaScript
const box = document.getElementById("snap-box");
const out = document.getElementById("out");
let changing = 0;
let changed = 0;

box.addEventListener("scrollsnapchanging", () => {
  changing += 1;
  out.textContent = "changing=" + changing + " · change=" + changed;
});

box.addEventListener("scrollsnapchange", () => {
  changed += 1;
  out.textContent = "changing=" + changing + " · change=" + changed;
});
Try It Yourself

How It Works

One gesture can update the pending target several times, then finish with a single scrollsnapchange.

🚀 Common Use Cases

  • Preview which carousel card would become active before the user releases.
  • Update soft focus / ghost highlights while dragging a snap rail.
  • Drive page-dot “hover” state during a slow scrollbar or touch drag.
  • Prefetch media for the pending slide before selection commits.
  • Pair with scrollsnapchange for preview vs committed UI.

🔧 How It Works

1

CSS snap container

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

Setup
2

Gesture in progress

User still scrolling; browser updates the potential rest target.

During
3

scrollsnapchanging

SnapEvent reports the pending snapTargetBlock / Inline.

Event
4

Then scrollsnapchange

On release, the selected target is committed (then scrollend).

📝 Notes

  • MDN: Experimental + Limited availability — Experimental banner shown; not Deprecated / Non-standard.
  • Requires CSS scroll snap on the scrolling element and its children.
  • Fires during the gesture; may fire multiple times per gesture.
  • Not every crossed snap child—only the potential rest target.
  • Related learning: scrollsnapchange, scrollend, addEventListener(), JavaScript hub.

Limited Browser Availability

scrollsnapchanging 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 scrollsnapchanging

Fires when a pending scroll snap target changes during a gesture. 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
scrollsnapchanging Limited

Bottom line: Use CSS scroll snap first, style the pending SnapEvent target during the gesture, then commit with scrollsnapchange.

Conclusion

scrollsnapchanging is the live “pending snap” signal during a scroll gesture. Style snapTargetBlock / snapTargetInline for previews, then use scrollsnapchange when the selection commits.

Continue with securitypolicyviolation, scrollsnapchange, addEventListener(), or the JavaScript hub.

💡 Best Practices

✅ Do

  • Set up CSS scroll snap before relying on the event
  • Clear previous pending styles on each update
  • Null-check snapTargetBlock / snapTargetInline
  • Use scrollsnapchange for committed UI / analytics
  • Feature-detect with "onscrollsnapchanging" in window

❌ Don’t

  • Treat pending previews as final selection
  • Assume it fires for every snap child you scroll past
  • Ship without a fallback outside Chromium
  • Skip CSS scroll-snap-type / scroll-snap-align
  • Overwrite onscrollsnapchanging if you need multiple listeners

Key Takeaways

Knowledge Unlocked

Five things to remember about scrollsnapchanging

Pending snap during the gesture—preview now, commit later.

5
Core concepts
📄02

SnapEvent

snapTarget*

API
03

vs change

pending vs final

Compare
📈04

Multi-fire

per gesture

Behavior
🎯05

Experimental

Chromium today

Status

❓ Frequently Asked Questions

It fires on a scroll container during a scrolling gesture when the browser decides a new snap target is pending—the one that will be selected when the gesture ends.
MDN marks Element scrollsnapchanging 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 pending snap targets on each axis.
Yes. It can fire multiple times as the user moves over potential snap targets. It does not fire for every crossed target—only for the last target the snap would potentially rest on.
scrollsnapchanging reports the pending target during the gesture. scrollsnapchange fires at the end when a new snap target is actually selected (just before scrollend).
Set scroll-snap-type on the scroll container and scroll-snap-align on child snap targets so the browser has something to snap to.
Did you know?

Even if you scroll across several snap cards in one drag, scrollsnapchanging only reports the target the browser would rest on now—not every intermediate card you passed.

Next: securitypolicyviolation

Handle Content Security Policy violation events in the page.

securitypolicyviolation →

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