JavaScript Element gesturechange Event

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

What You’ll Learn

The gesturechange event fires while fingers move during a WebKit multi-touch gesture. Learn scale / rotation, ongesturechange, gesturestart / gestureend, portable alternatives, and five try-it labs.

01

Kind

Instance event

02

Type

GestureEvent

03

When

Digits move mid-gesture

04

Handler

ongesturechange

05

Key fields

scale / rotation

06

Status

Non-standard

Introduction

Pinch-to-zoom and two-finger rotate feel natural on phones. WebKit exposed that motion with a small family of events: gesturestart, gesturechange, and gestureend, using the GestureEvent interface.

gesturechange is the “while moving” update. Other browsers never standardized it. For production apps, treat it as an optional Safari path—not the only path.

💡
Beginner tip

On Chrome/Firefox desktop, these listeners often never run. Always feature-detect ("ongesturechange" in window or window.GestureEvent) and keep a Touch / Pointer fallback.

Understanding gesturechange

An instance event that answers: “Are the user’s fingers still moving during an active multi-touch gesture?”

  • Non-standard WebKit proprietary event (not in a public spec).
  • Fires when digits move after a gesture has started.
  • GestureEvent — exposes scale and rotation.
  • Handlerongesturechange or addEventListener("gesturechange", ...).
  • Familygesturestartgesturechange* → gestureend.

📝 Syntax

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

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

ongesturechange = (event) => { };

Event type

A GestureEvent (inherits from UIEvent and Event).

Handy properties

PropertyMeaning
scaleFinger-distance multiplier vs gesture start (1.0 initial; <1 pinch; >1 spread)
rotationDegrees rotated since gesture start (positive = clockwise; initial 0.0)

🔁 Event Order

  1. gesturestart — multiple fingers begin a gesture
  2. gesturechange — repeated while digits move
  3. gestureend — gesture finishes

⚖️ WebKit gestures vs portable APIs

ApproachProsCons
gesturechangeBuilt-in scale / rotationNon-standard; WebKit-only
Touch EventsWide mobile supportYou compute pinch math yourself
Pointer EventsMouse + touch + pen unifiedMore setup for multi-pointer tracking
wheel (+ modifiers)Useful on some desktop trackpadsNot a full substitute for multi-touch rotate

⚡ Quick Reference

GoalCode / note
Listen (WebKit)el.addEventListener("gesturechange", fn)
Handler propertyel.ongesturechange = fn
Read zoom factorevent.scale
Read twistevent.rotation
Feature-detect"GestureEvent" in window
MDN statusNon-standard

🔍 At a Glance

Four facts to remember about gesturechange.

Event type
GestureEvent

WebKit proprietary

Means
digits moving

Mid-gesture

Fields
scale · rotation

Pinch & twist

Status
non-standard

Not for sole use

Examples Gallery

Examples follow MDN Element: gesturechange event. Real pinch gestures need a WebKit touch device; labs also show detect / simulate paths.

📚 Getting Started

Basic listeners and the handler property.

Example 1 — Log scale and rotation

Print GestureEvent fields while a WebKit gesture is active.

JavaScript
const stage = document.getElementById("stage");
const out = document.getElementById("out");

stage.addEventListener("gesturechange", (event) => {
  out.textContent =
    "scale=" + event.scale.toFixed(3) +
    " rotation=" + event.rotation.toFixed(1) + "°";
});
Try It Yourself

How It Works

On unsupported browsers nothing appears until you use the detect / fallback labs.

Example 2 — ongesturechange Property

Same idea using the handler property form.

JavaScript
const stage = document.getElementById("stage");
const out = document.getElementById("out");

stage.ongesturechange = (event) => {
  out.textContent = "ongesturechange scale=" + event.scale.toFixed(3);
};
Try It Yourself

How It Works

Prefer addEventListener when you need multiple listeners or easy removal.

📈 Detect, Transform & Fallback

Feature-detect WebKit support, apply CSS, keep a touch path.

Example 3 — Feature-Detect GestureEvent

Tell learners whether this engine exposes the proprietary API.

JavaScript
const out = document.getElementById("out");
const supported = typeof window.GestureEvent === "function" ||
  "ongesturechange" in window;

out.textContent = supported
  ? "GestureEvent / ongesturechange looks available (likely WebKit)."
  : "No GestureEvent here — use Touch/Pointer fallback.";

if (supported) {
  document.getElementById("stage").addEventListener("gesturechange", (e) => {
    out.textContent = "Live scale=" + e.scale.toFixed(3);
  });
}
Try It Yourself

How It Works

Detection strings vary by engine. Treat any positive result as “optional enhancement,” not a guarantee of touch hardware.

Example 4 — Apply Scale with CSS Transform

Map event.scale onto a visual element during the gesture.

JavaScript
const stage = document.getElementById("stage");
const card = document.getElementById("card");
let base = 1;

stage.addEventListener("gesturestart", (event) => {
  event.preventDefault();
  base = Number(card.dataset.scale || 1);
});

stage.addEventListener("gesturechange", (event) => {
  event.preventDefault();
  const next = base * event.scale;
  card.style.transform = "scale(" + next + ")";
  card.dataset.live = String(next);
});

stage.addEventListener("gestureend", () => {
  card.dataset.scale = card.dataset.live || card.dataset.scale || "1";
});
Try It Yourself

How It Works

preventDefault() may be required to stop the browser’s own page zoom. Use a non-passive listener when you need cancelable behavior.

Example 5 — Portable Two-Touch Distance Fallback

Compute a simple pinch factor from Touch Events when GestureEvent is missing.

JavaScript
const stage = document.getElementById("stage");
const out = document.getElementById("out");
let startDist = 0;

function distance(t0, t1) {
  const dx = t0.clientX - t1.clientX;
  const dy = t0.clientY - t1.clientY;
  return Math.hypot(dx, dy);
}

stage.addEventListener("touchstart", (event) => {
  if (event.touches.length === 2) {
    startDist = distance(event.touches[0], event.touches[1]);
  }
}, { passive: true });

stage.addEventListener("touchmove", (event) => {
  if (event.touches.length === 2 && startDist > 0) {
    const scale = distance(event.touches[0], event.touches[1]) / startDist;
    out.textContent = "touch pinch scale≈" + scale.toFixed(3);
  }
}, { passive: true });

if ("GestureEvent" in window) {
  stage.addEventListener("gesturechange", (event) => {
    out.textContent = "gesturechange scale=" + event.scale.toFixed(3);
  });
}
Try It Yourself

How It Works

This is the beginner-friendly portable approach. Keep GestureEvent as an optional WebKit shortcut when present.

🚀 Common Use Cases (WebKit / Learning)

  • Reading Safari / iOS samples that mention GestureEvent.
  • Optional Safari enhancement on top of a Touch Events core path.
  • Photo / map demos that need quick scale / rotation values.
  • Interview questions comparing proprietary vs standard input APIs.
  • Understanding why cross-browser libraries roll their own pinch math.

🔧 How It Works (When Supported)

1

Two+ fingers contact

gesturestart begins; scale starts at 1.0.

Start
2

Fingers move

gesturechange updates scale / rotation.

Change
3

Your UI updates

Apply CSS transforms or zoom a canvas layer.

Render
4

gestureend

Commit the final scale and clear temporary state.

📝 Notes

  • MDN: Non-standard — status banner required before What You’ll Learn.
  • Not Deprecated or Experimental on the MDN Element page for this event.
  • WebKit proprietary—not for sole use in cross-browser products.
  • Prefer Touch / Pointer math (or library helpers) as the default path.
  • Related learning: fullscreenerror, gestureend, addEventListener(), JavaScript hub.

Non-standard / WebKit Support

gesturechange is marked Non-standard on MDN. Logos use the shared browser-image-sprite.png sprite from this project. Expect WebKit/Safari paths only—always ship a Touch or Pointer fallback.

Non-standard

Element gesturechange

Proprietary WebKit multi-touch gesture updates; not a portable primary API.

WebKit Not standardized
Google Chrome No GestureEvent; use Touch/Pointer
No
Mozilla Firefox No GestureEvent; use Touch/Pointer
No
Apple Safari WebKit GestureEvent (esp. iOS)
WebKit
Microsoft Edge No GestureEvent; use Touch/Pointer
No
Opera No GestureEvent; use Touch/Pointer
No
Internet Explorer No
No
gesturechange Non-standard

Bottom line: Use GestureEvent only as an optional Safari enhancement; compute pinch with Touch/Pointer Events for everyone else.

Conclusion

gesturechange is a Non-standard WebKit signal for mid-gesture pinch and rotate. Know scale and rotation, feature-detect carefully, and keep Touch / Pointer Events as your portable foundation.

Continue with gestureend, addEventListener(), or the JavaScript hub.

💡 Best Practices

✅ Do

  • Feature-detect before attaching GestureEvent listeners
  • Keep a Touch / Pointer pinch implementation as the default
  • Document that the API is WebKit-only / Non-standard
  • Test on real iOS Safari hardware when you enhance with it
  • Pair with gesturestart / gestureend for full lifecycle

❌ Don’t

  • Ship pinch/zoom that only listens for gesturechange
  • Assume Chrome or Firefox will fire these events
  • Ignore browser page-zoom side effects (consider preventDefault)
  • Treat Non-standard as “fine for all production users”
  • Overwrite ongesturechange if you need multiple listeners

Key Takeaways

Knowledge Unlocked

Five things to remember about gesturechange

WebKit mid-gesture updates—Non-standard; prefer portable pinch math.

5
Core concepts
📄 02

GestureEvent

scale · rotation

API
🚫 03

Non-standard

WebKit only

Status
🔄 04

Touch fallback

portable pinch

Replace
🎯 05

Feature-detect

optional enhance

Pattern

❓ Frequently Asked Questions

It is a proprietary WebKit event fired when fingers move during a multi-touch gesture. It exposes GestureEvent.scale and GestureEvent.rotation. MDN marks it Non-standard.
MDN marks it Non-standard only on the Element gesturechange page — not Deprecated and not Experimental. Still avoid it as the primary API in cross-browser apps.
It is WebKit-specific. Expect Safari on iOS (and related WebKit contexts). Chrome, Firefox, and Edge generally do not implement this event.
scale is a multiplier of the initial finger distance (1.0 at start; <1 pinch out/zoom out; >1 spread/zoom in). rotation is degrees since the gesture began (positive = clockwise).
For portable pinch/zoom, prefer Touch Events or Pointer Events and compute distance yourself, or use wheel with ctrlKey where the platform emits it. Feature-detect GestureEvent only as an optional Safari enhancement.
gesturestart begins the gesture, gesturechange fires while digits move, and gestureend fires when the gesture finishes.
Did you know?

MDN lists gesturechange under “Not part of any specification.” That is why libraries rarely depend on it alone—standards favor Touch Events and Pointer Events for multi-touch.

Next: gestureend

Learn the WebKit signal that a multi-touch gesture has finished.

gestureend →

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