wheel

This article is in need of a technical review.

The wheel event is fired when a wheel button of a pointing device (usually a mouse) is rotated. This event deprecates the legacy mousewheel event.

General info

Specification
DOM L3
Interface
WheelEvent
Synchronicity
asynchronous
Bubbles
Yes
Cancelable
Yes
Target
defaultView, Document, Element
Default Action
Scroll, moving history, or zooming in/out.

Properties

Property Type Description
target Read only EventTarget The event target (the topmost target in the DOM tree).
type Read only DOMString The type of event.
bubbles Read only boolean Does the event normally bubble?
cancelable Read only boolean Is it possible to cancel the event?
view Read only WindowProxy document.defaultView (the window of the document).
detail Read only long (float) 0.
currentTarget Read only EventTarget (DOM element) The node that had the event listener attached.
relatedTarget Read only EventTarget (DOM element) For mouseover, mouseout, mouseenter and mouseleave events: the target of the complementary event (the mouseleave target in the case of a mouseenter event). null otherwise.
screenX Read only long (int) The X coordinate of the mouse pointer in global (screen) coordinates.
screenY Read only long (int) The Y coordinate of the mouse pointer in global (screen) coordinates.
clientX Read only long (int) The X coordinate of the mouse pointer in local (DOM content) coordinates.
clientY Read only long (int) The Y coordinate of the mouse pointer in local (DOM content) coordinates.
button Read only unsigned short (int) The button number that was pressed when the mouse event was fired: Left button=0, middle button=1 (if present), right button=2. For mice configured for left handed use in which the button actions are reversed the values are instead read from right to left.
buttons Read only DOM level 3 unsigned short (int) The buttons being pressed when the mouse event was fired: Left button=1, Right button=2, Middle (wheel) button=4, 4th button (typically, "Browser Back" button)=8, 5th button (typically, "Browser Forward" button)=16. If two or more buttons are pressed, returns the logical sum of the values. E.g., if Left button and Right button are pressed, returns 3 (=1 | 2). More info.
mozPressure Read only float The amount of pressure applied to a touch or tabdevice when generating the event; this value ranges between 0.0 (minimum pressure) and 1.0 (maximum pressure).
deltaMode unsigned long (int) Unit indicator (pixels, lines, or pages) for the deltaX, deltaY, and deltaZ attributes. Read only.
deltaX float Expected amount that the page will scroll along the x-axis according to the deltaMode units; or an implementation-specific value of movement of a wheel around the x-axis. Read Only.
deltaY float Expected amount that the page will scroll along the y-axis according to the deltaMode units; or an implementation-specific value of movement of a wheel around the y-axis. Read Only.
deltaZ float Expected amount that the page will scroll along the z-axis according to the deltaMode units; or an implementation-specific value of movement of a wheel around the z-axis. Read Only.

Browser compatibility

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support 31 17.0 (17.0) 9.0[2] Not supported ?
Feature Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support ? 17.0 (17.0) ? ? ?

[1] Internet Explorer exposes the wheel event only via addEventListener, there is no onwheel attribute on DOM objects. Bug report.

Listening to this event across browser

The following script creates a global addWheelListener method that allows to listen to the different wheel events across browsers and prevent the default behavior.

// creates a global "addWheelListener" method
// example: addWheelListener( elem, function( e ) { console.log( e.deltaY ); e.preventDefault(); } );
(function(window,document) {

    var prefix = "", _addEventListener, onwheel, support;

    // detect event model
    if ( window.addEventListener ) {
        _addEventListener = "addEventListener";
    } else {
        _addEventListener = "attachEvent";
        prefix = "on";
    }

    // detect available wheel event
    support = "onwheel" in document.createElement("div") ? "wheel" : // Modern browsers support "wheel"
              document.onmousewheel !== undefined ? "mousewheel" : // Webkit and IE support at least "mousewheel"
              "DOMMouseScroll"; // let's assume that remaining browsers are older Firefox

    window.addWheelListener = function( elem, callback, useCapture ) {
        _addWheelListener( elem, support, callback, useCapture );

        // handle MozMousePixelScroll in older Firefox
        if( support == "DOMMouseScroll" ) {
            _addWheelListener( elem, "MozMousePixelScroll", callback, useCapture );
        }
    };

    function _addWheelListener( elem, eventName, callback, useCapture ) {
        elem[ _addEventListener ]( prefix + eventName, support == "wheel" ? callback : function( originalEvent ) {
            !originalEvent && ( originalEvent = window.event );

            // create a normalized event object
            var event = {
                // keep a ref to the original event object
                originalEvent: originalEvent,
                target: originalEvent.target || originalEvent.srcElement,
                type: "wheel",
                deltaMode: originalEvent.type == "MozMousePixelScroll" ? 0 : 1,
                deltaX: 0,
                delatZ: 0,
                preventDefault: function() {
                    originalEvent.preventDefault ?
                        originalEvent.preventDefault() :
                        originalEvent.returnValue = false;
                }
            };
            
            // calculate deltaY (and deltaX) according to the event
            if ( support == "mousewheel" ) {
                event.deltaY = - 1/40 * originalEvent.wheelDelta;
                // Webkit also support wheelDeltaX
                originalEvent.wheelDeltaX && ( event.deltaX = - 1/40 * originalEvent.wheelDeltaX );
            } else {
                event.deltaY = originalEvent.detail;
            }

            // it's time to fire the callback
            return callback( event );

        }, useCapture || false );
    }

})(window,document);

Gecko notes

The event order with legacy mouse scroll events

If a trusted wheel event is not consumed, a DOMMouseScroll event and a MozMousePixelScroll event are fired for backward compatibility. Their attribute values are computed from the wheel event's delta values and the nearest ancestor clipped element (i.e., overflow is not visible). If either wheel event or one of the legacy events is consumed by event.preventDefault(), nothing happens.

The event order is:

  1. A wheel event in the default event group (both web applications and add-ons can handle the events in this group)
  2. A vertical DOMMouseScroll event in both event group if accumulated deltaY of consecutive wheel events become larger than 1.0 or less than -1.0
  3. A vertical MozMousePixelScroll event in both event group if deltaY of the latest wheel event isn't zero
  4. A horizontal DOMMouseScroll event in both event group if accumulated deltaX of consecutive wheel events become larger than 1.0 or less than -1.0
  5. A horizontal MozMousePixelScroll event in both event group if deltaX of the latest wheel event isn't zero
  6. A wheel event in the system group (only add-ons can handle in this group)
What happens if preventDefault() of each event called?
wheel (default event group) preventDefault() called        
DOMMouseScroll (Vertical) Not fired preventDefault() called      
MozMousePixelScroll (Vertical) Not fired defaultPrevented is true preventDefault() called    
DOMMouseScroll (Horizontal) Not fired Not affected Not affected preventDefault() called  
MozMousePixelScroll (Horizontal) Not fired Not affected Not affected defaultPrevented is true preventDefault() called
wheel (system event group) defaultPrevented is true defaultPrevented is true defaultPrevented is true defaultPrevented is true defaultPrevented is true

If an Add-on needs to know if one of legacy events are consumed by web contents, it can use the wheel event of #6. See the document of nsIEventListenerService for the detail of system event group.

The delta values and default action of trusted events can be customized by user preferences (details). Therefore, any web developers shouldn't expect a particular action would occur after receiving this event.

The delta values

The delta values do not indicate the actual scroll amount by default. If the user was holding a modifier key when moving the scroll wheel, the wheel action may cause another action such as moving forward or backward through browser history or zooming in or out. In addition, even when scrolling, the scrolled element may be different from its event target. The wheel event target is computed only from the mouse cursor position at the time at which the event was fired. That event may not only not be the one actually being scrolled, but may not even be scrollable.

The deltaMode value

On Windows, following 3 native events cause DOM wheel events.

WM_MOUSEWHEEL (Vertical mouse wheel event)
The deltaMode can be DOM_DELTA_LINE or DOM_DELTA_PAGE. It depends on user settings of Windows (The defualt setting causes DOM_DELTA_LINE).
WM_MOUSEHWHEEL (Horizontal mouse wheel event)
The deltaMode can be DOM_DELTA_LINE or DOM_DELTA_PAGE. However, neither wheel scroll speed setting dialog of Windows nor similar UI of each mouse driver's utility typically has the UI to change to page scroll. So, typically, this value is DOM_DELTA_LINE.
WM_GESTURE (Only when caused by panning)
The deltaMode is always DOM_DELTA_PIXEL. But note that most touchpad devices of notebook emulate mouse wheel events rather than using this event. This event it typically used on tablet PC.

On Mac, deltaMode value depends on the device. If the device supports high resolution scroll by pixels, deltaMode value is typically DOM_DELTA_PIXEL. However, the user can change it to DOM_DELTA_LINE with "mousewheel.enable_pixel_scrolling" pref.  If the device doesn't support high resolution scroll, it's always DOM_DELTA_LINE.

On other platforms, the deltaMode value is always DOM_DELTA_LINE.

Untrusted events

Untrusted wheel events never cause any default action.

See also

Document Tags and Contributors

Last updated by: brianblakely,