JavaScript Element gestureend Event

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

What You’ll Learn

The gestureend event fires when a WebKit multi-touch gesture finishes. Learn final scale / rotation, ongestureend, gesturestart / gesturechange, portable alternatives, and five try-it labs.

01

Kind

Instance event

02

Type

GestureEvent

03

When

Multi-touch gesture ends

04

Handler

ongestureend

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.

gestureend is the “gesture finished” signal—ideal for committing a final transform or clearing temporary state. Other browsers never standardized it. 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 ("ongestureend" in window or window.GestureEvent) and keep a Touch / Pointer fallback.

Understanding gestureend

An instance event that answers: “Have the user’s fingers finished a multi-touch gesture (no longer multiple contacts)?”

  • Non-standard WebKit proprietary event (not in a public spec).
  • Fires when multiple fingers are no longer contacting the surface.
  • GestureEvent — final scale and rotation.
  • Handlerongestureend or addEventListener("gestureend", ...).
  • Familygesturestartgesturechange* → gestureend.

📝 Syntax

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

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

ongestureend = (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
gestureendFinal scale / rotation at gesture endNon-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("gestureend", fn)
Handler propertyel.ongestureend = fn
Read zoom factorevent.scale
Read twistevent.rotation
Feature-detect"GestureEvent" in window
MDN statusNon-standard

🔍 At a Glance

Four facts to remember about gestureend.

Event type
GestureEvent

WebKit proprietary

Means
gesture finished

End of multi-touch

Fields
scale · rotation

Pinch & twist

Status
non-standard

Not for sole use

Examples Gallery

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

📚 Getting Started

Basic listeners and the handler property.

Example 1 — Log Final scale and rotation

Print GestureEvent fields when a WebKit multi-touch gesture ends.

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

stage.addEventListener("gestureend", (event) => {
  out.textContent =
    "final 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 — ongestureend Property

Same idea using the handler property form.

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

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

How It Works

Prefer addEventListener when you need multiple listeners or easy removal.

📈 Detect, Commit & Fallback

Feature-detect WebKit support, commit on gestureend, 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" ||
  "ongestureend" in window;

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

if (supported) {
  document.getElementById("stage").addEventListener("gestureend", (e) => {
    out.textContent = "Ended with 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 — Commit Scale on gestureend

Preview during gesturechange, then persist the final scale when the gesture ends.

JavaScript
const stage = document.getElementById("stage");
const card = document.getElementById("card");
const out = document.getElementById("out");
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", (event) => {
  const committed = Number(card.dataset.live || base * event.scale);
  card.dataset.scale = String(committed);
  card.style.transform = "scale(" + committed + ")";
  out.textContent = "Committed scale=" + committed.toFixed(3);
});
Try It Yourself

How It Works

gestureend is where you lock in the result. preventDefault() on earlier gesture events may still be needed to reduce the browser’s own page zoom.

Example 5 — Portable touchend Commit Fallback

When GestureEvent is missing, commit the pinch factor when the second finger lifts.

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

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) {
    liveScale = distance(event.touches[0], event.touches[1]) / startDist;
    out.textContent = "live scale≈" + liveScale.toFixed(3);
  }
}, { passive: true });

stage.addEventListener("touchend", (event) => {
  if (event.touches.length < 2 && startDist > 0) {
    out.textContent = "committed (touchend) scale≈" + liveScale.toFixed(3);
    startDist = 0;
  }
}, { passive: true });

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

How It Works

Commit on touchend (when fewer than two touches remain) mirrors gestureend. Keep GestureEvent as an optional WebKit shortcut.

🚀 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 commit zoom when the pinch gesture ends.
  • 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

Preview updates

Apply live CSS transforms during gesturechange.

Preview
4

gestureend fires

Commit final scale / rotation and clear temp 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: gesturechange, gesturestart, addEventListener(), JavaScript hub.

Non-standard / WebKit Support

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

Proprietary WebKit multi-touch gesture end signal; 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
gestureend Non-standard

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

Conclusion

gestureend is a Non-standard WebKit signal that a multi-touch gesture finished. Use it to commit final scale / rotation, feature-detect carefully, and keep Touch / Pointer Events as your portable foundation.

Continue with gesturestart, 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 / gesturechange for full lifecycle

❌ Don’t

  • Ship pinch/zoom that only listens for gestureend
  • 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 ongestureend if you need multiple listeners

Key Takeaways

Knowledge Unlocked

Five things to remember about gestureend

WebKit gesture finished—Non-standard; prefer portable commit on touchend.

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 there are no longer multiple fingers on the touch surface, ending the gesture. The event object is a GestureEvent with scale and rotation. MDN marks it Non-standard.
MDN marks it Non-standard only on the Element gestureend page — not Deprecated and not Experimental. Still avoid it as the primary API in cross-browser apps.
gesturestart begins the gesture, gesturechange fires while fingers move, and gestureend fires when the multi-touch gesture finishes.
It is WebKit-specific. Expect Safari on iOS (and related WebKit contexts). Chrome, Firefox, and Edge generally do not implement this event.
They report the final GestureEvent values for that gesture: scale relative to the start distance, and rotation in degrees since the gesture began.
For portable pinch/zoom, prefer Touch Events or Pointer Events and commit when the second finger lifts (for example touchend). Feature-detect GestureEvent only as an optional Safari enhancement.
Did you know?

MDN lists gestureend 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: gesturestart

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

gesturestart →

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