JavaScript Element wheel Event

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

What You’ll Learn

The wheel event fires when the user rotates a mouse wheel or a related device (trackpad, mouse ball). Learn addEventListener vs onwheel, WheelEvent deltas, passive listeners, how it differs from scroll, custom zoom with preventDefault, and five try-it labs.

01

Kind

Instance event

02

Type

WheelEvent

03

When

Wheel / trackpad rotate

04

Handler

onwheel

05

Bubbles?

Yes

06

Status

Limited availability

Introduction

wheel answers: “Did the user turn a wheel or trackpad?” That is an input intent signal—not a guarantee that content scrolled. It is also the modern replacement for the obsolete mousewheel event.

Zooming with Ctrl + wheel / trackpad pinch often fires wheel with ctrlKey set to true. Canceling the event can block scrolling or zooming, but blocking every wheel can hurt scroll performance—prefer { passive: true } when you only listen.

💡
Beginner tip

Need to know if the page actually moved? Listen for scroll and read scrollTop / scrollLeft. Do not trust deltaY alone as the scroll direction.

Understanding wheel

An instance event that answers: “Did a pointing device report a wheel-like rotation over this element?”

  • Trigger — mouse wheel, trackpad scroll gesture, or similar.
  • Event typeWheelEvent with deltaX, deltaY, deltaZ, deltaMode.
  • Bubbles — yes; can be listened for on ancestors.
  • Cancelable — yes (sometimes only the first event in a sequence).
  • Limited availability on MDN (not Baseline)—notably missing on Safari iOS.

📝 Syntax

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

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

onwheel = (event) => { };

Event type

A WheelEvent (inherits from MouseEvent, UIEvent, and Event).

Handy WheelEvent properties

PropertyMeaning
deltaXHorizontal scroll amount (read-only double)
deltaYVertical scroll amount (read-only double)
deltaZZ-axis scroll amount (read-only double)
deltaModeUnit for deltas: pixels (0), lines (1), or pages (2)

deltaMode constants

ConstantValueUnit
WheelEvent.DOM_DELTA_PIXEL0x00Pixels
WheelEvent.DOM_DELTA_LINE0x01Lines
WheelEvent.DOM_DELTA_PAGE0x02Pages

⚡ Passive Listeners & Cancelability

Canceling wheel (via preventDefault()) can stop scrolling or zooming. MDN notes that in some browsers only the first wheel event in a sequence is cancelable. Waiting on every wheel handler before scrolling can cause jank.

  • Observing only? Use addEventListener("wheel", fn, { passive: true }).
  • Need to cancel (custom zoom, custom scroll)? Use { passive: false } and call preventDefault() carefully.
  • Keep handlers light—wheel can fire at a high rate on trackpads.

⚡ Quick Reference

GoalCode / note
Listenel.addEventListener("wheel", fn)
Handler propertyel.onwheel = fn
Vertical deltaevent.deltaY
Observe only{ passive: true }
Custom zoompreventDefault() + scale transform
Scroll directionUse scroll + scrollTop, not deltaY
MDN statusLimited availability (not Baseline)

🔍 At a Glance

Four facts to remember about wheel.

Event type
WheelEvent

deltaX / deltaY

Means
wheel rotated

Not always scroll

Bubbles
true

Cancelable too

Baseline
no

Limited availability

Examples Gallery

Examples follow MDN Element: wheel event. Use a mouse wheel or trackpad over each try-it lab.

📚 Getting Started

Listener and handler-property patterns.

Example 1 — Log wheel with addEventListener

Detect wheel / trackpad input and show deltaY.

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

pad.addEventListener("wheel", (event) => {
  out.textContent = "wheel deltaY=" + event.deltaY.toFixed(1);
}, { passive: true });
Try It Yourself

How It Works

passive: true tells the browser you will not call preventDefault(), so scrolling stays smooth.

Example 2 — onwheel Property

Same idea using the handler property form.

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

pad.onwheel = (event) => {
  out.textContent = "onwheel fired (deltaY=" + event.deltaY.toFixed(1) + ")";
};
Try It Yourself

How It Works

Prefer addEventListener when you need multiple listeners, options like passive, or easy removal.

📈 Deltas, Zoom & Scroll Compare

Inspect WheelEvent fields, scale an element, and contrast with scroll.

Example 3 — Read deltaX / deltaY / deltaMode

Show horizontal and vertical deltas plus the unit mode.

JavaScript
const pad = document.getElementById("pad");
const out = document.getElementById("out");
const modes = ["PIXEL", "LINE", "PAGE"];

pad.addEventListener("wheel", (event) => {
  out.textContent =
    "dx=" + event.deltaX.toFixed(1) +
    " dy=" + event.deltaY.toFixed(1) +
    " mode=" + (modes[event.deltaMode] || event.deltaMode);
}, { passive: true });
Try It Yourself

How It Works

deltaMode tells you whether deltas are in pixels, lines, or pages—important when normalizing input across devices.

Example 4 — Scale an Element via the Wheel (MDN)

Cancel the default action and zoom with deltaY (MDN pattern).

JavaScript
let scale = 1;
const el = document.querySelector("#zoom-box");

function zoom(event) {
  event.preventDefault();
  scale += event.deltaY * -0.01;
  scale = Math.min(Math.max(0.125, scale), 4);
  el.style.transform = "scale(" + scale + ")";
}

el.addEventListener("wheel", zoom, { passive: false });
Try It Yourself

How It Works

{ passive: false } is required so preventDefault() can block page scroll while you own the zoom gesture.

Example 5 — wheel vs scroll

Log both events on an overflow box to see when each fires.

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

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

box.addEventListener("wheel", () => push("wheel"), { passive: true });
box.addEventListener("scroll", () => {
  push("scroll top=" + Math.round(box.scrollTop));
});
Try It Yourself

How It Works

At the end of the pane you may still see wheel without further scroll. Keyboard scrolling can fire scroll without wheel.

🚀 Common Use Cases

  • Custom zoom / scale for maps, canvases, and image viewers.
  • Detecting trackpad / wheel intent before content scrolls.
  • Horizontal gallery navigation when deltaX dominates.
  • Teaching tools that visualize input deltas for beginners.
  • Migrating from deprecated mousewheel to standard wheel.

🔧 How It Works

1

Pointer over target

Mouse / trackpad is over the element (or an ancestor listener).

Setup
2

Wheel rotates

User turns the wheel or performs a trackpad scroll gesture.

Input
3

wheel fires

WheelEvent with deltas; may be canceled if not passive.

Event
4

Scroll, zoom, or custom UI

Browser may scroll/zoom, or your handler owns the gesture.

📝 Notes

  • MDN: Limited availability (not Baseline)—no Deprecated / Experimental / Non-standard banner.
  • Safari on iOS generally does not support Element wheel.
  • Prefer { passive: true } unless you must call preventDefault().
  • Do not use delta* as the source of truth for scroll direction.
  • Related learning: scroll, scrollend, mousewheel, addEventListener(), JavaScript hub.

Limited Browser Availability

wheel is marked Limited availability on MDN (not Baseline). Logos use the shared browser-image-sprite.png sprite from this project. Desktop browsers are strong; Safari on iOS typically does not expose Element wheel—pair with scroll for mobile scroll UIs.

Limited availability

Element wheel

Fires on mouse wheel / trackpad rotation. Chrome, Firefox, Edge, Opera, and desktop Safari support it; Safari iOS generally does not.

Partial Not Baseline
Google Chrome 31+
Supported
Mozilla Firefox 17+
Supported
Apple Safari 7+ desktop · iOS no
Partial
Microsoft Edge 12+
Supported
Opera Chromium-based yes
Supported
Internet Explorer 9+ (legacy)
Supported
wheel Limited

Bottom line: Use wheel for desktop wheel/trackpad intent and custom zoom. For “did content move?”, listen to scroll and read scrollTop/scrollLeft.

Conclusion

wheel is the standard signal that a mouse wheel or trackpad rotated. Read WheelEvent deltas for intent, use passive listeners when you only observe, and rely on scroll when you need the real scroll direction.

Continue with scroll, mousewheel, addEventListener(), or the JavaScript hub.

💡 Best Practices

✅ Do

  • Use standard wheel instead of mousewheel
  • Prefer { passive: true } for observe-only handlers
  • Check deltaMode when normalizing deltas
  • Use scroll for scroll direction / position
  • Set { passive: false } only when you must cancel

❌ Don’t

  • Assume wheel always causes scroll
  • Treat deltaY as scroll direction truth
  • Call preventDefault() with a passive listener
  • Expect Safari iOS to fire Element wheel
  • Overwrite onwheel if you need multiple listeners

Key Takeaways

Knowledge Unlocked

Five things to remember about wheel

Wheel rotated—deltas for intent, scroll for position.

5
Core concepts
📄02

WheelEvent

deltaX / deltaY

API
03

vs scroll

intent ≠ offset

Compare
04

Passive

smooth scrolling

Perf
🎯05

Limited

not Baseline

Status

❓ Frequently Asked Questions

It fires when the user rotates a wheel button on a pointing device (typically a mouse), or uses related inputs such as a trackpad that simulate wheel actions. The event type is WheelEvent.
No. MDN does not mark Element wheel as Deprecated, Experimental, or Non-standard. It has Limited availability (not Baseline), mainly because Safari on iOS does not support it. It replaces the deprecated non-standard mousewheel event.
A WheelEvent, which inherits from MouseEvent, UIEvent, and Event. Useful read-only properties include deltaX, deltaY, deltaZ, and deltaMode.
wheel means the user rotated a wheel or trackpad — it may or may not scroll. scroll means the scroll offset actually changed. Zoom gestures can fire wheel with ctrlKey true. Keyboard or scrollbar scrolling can fire scroll without wheel.
No. MDN warns that even when wheel triggers scrolling, delta* values do not necessarily match content scroll direction. Prefer watching scrollLeft / scrollTop on the scroll event.
When you only observe the wheel and do not call preventDefault(). Passive listeners let the browser scroll without waiting on your handler, which avoids jank. Use { passive: false } only when you must cancel the event (for example custom zoom).
Did you know?

Ctrl + wheel / trackpad pinch often fires wheel with ctrlKey === true. That is how many apps detect zoom intent without waiting for a separate gesture API.

Next: addEventListener()

Master options like passive for wheel and other DOM events.

addEventListener() →

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