The Pointer Events specification defines a unified hardware-agnostic framework for handling input from various devices, including mice, touchscreens, and pens/styluses. By providing a single set of events (e.g., pointerdown, pointermove, pointerup), it allows developers to support diverse input methods without writing device-specific logic for each.
This specification also defines Mouse and Wheel Events, as well as a mapping to fire Mouse Events for other pointer device types.
This specification is an update to [[PointerEvents3]] specification. It also includes the Mouse and Wheel Events, previously in the [[UIEVENTS]] specification.
This revision includes new features:
persistentDeviceId to provide a stable identifier for input devices across multiple interactions.touch-action values:pan-left,pan-right,pan-up,pan-downToday, most [[HTML]] content is used with and/or designed for mouse input. Those that handle input in a custom manner typically code to [[UIEVENTS]] Mouse Events. Newer computing devices today, however, incorporate other forms of input, including touchscreens and pen input. Event types have been proposed for handling each of these forms of input individually. However, that approach often incurs unnecessary duplication of logic and event handling overhead when adding support for a new input type. This often creates a compatibility problem when content is written with only one device type in mind. Additionally, for compatibility with existing mouse-based content, mostuser agents fire Mouse Events for all input types. This makes it ambiguous whether a Mouse Event represents an actual mouse device or is being produced from another input type for compatibility, which makes it hard to code to both device types simultaneously.
To reduce the cost of coding to multiple input types and also to help with the above described ambiguity with Mouse Events, this specification defines a more abstract form of input, called apointer. A pointer can be any point of contact on the screen made by a mouse cursor, pen, touch (including multi-touch), or other pointing input device. This model makes it easier to write sites and applications that work well no matter what hardware the user has. For scenarios when device-specific handling is desired, this specification also defines properties for inspecting the device type which produced the event. The primary goal is to provide a single set of events and interfaces that allow for easier authoring for cross-device pointer input while still allowing for device-specific handling only when necessary for an augmented experience.
An additional key goal is to enable multi-threaded user agents to handledirect manipulation actions for panning and zooming (for instance, with a finger or stylus on a touchscreen), without blocking on script execution.
While this specification defines a unified event model for a variety of pointer inputs, this model does not cover other forms of input such as keyboards or keyboard-like interfaces (for instance, a screen reader or similar assistive technology running on a touchscreen-only device, which allows users sequential navigation through focusable controls and elements). While user agents might choose to also generate pointer events in response to these interfaces, this scenario is not covered in this specification.
In the first instance, authors are encouraged to provide equivalent functionality for all forms of input by responding to high-level events such as [=HTMLElement/focus=], [=HTMLElement/blur=] andclick. However, when using low-level events (such as Pointer Events), authors are encouraged to ensure that all types of input are supported. In the case of keyboards and keyboard-like interfaces, this might require the addition of explicit keyboard event handling. SeeKeyboard Accessible [[WCAG22]] for further details.

The events for handling generic pointer input look a lot like those for mouse: {{pointerdown}}, {{pointermove}}, {{pointerup}}, {{pointerover}}, {{pointerout}}, and so on. This facilitates easy content migration from Mouse Events to Pointer Events. Pointer Events provide all the usual properties present in Mouse Events (including client coordinates, target element, button states) in addition to new properties for other forms of input, such as pressure, contact geometry, tilt. Authors can easily code to Pointer Events to share logic between different input types where it makes sense, and customize for a particular type of input only where necessary to get the best experience.
While Pointer Events are sourced from a variety of input devices, they are not defined as being generated from some other set of device-specific events. While possible and encouraged for compatibility, this spec does not require other device-specific events be supported (such as mouse events or touch events). A user agent could support pointer events without supporting any other device events. For compatibility with content written to mouse-specific events, this specification does provide an optional section describing how to generatecompatibility mouse events based on pointer input from devices other than a mouse.
This specification does not provide any advice on the expected behavior of user agents that support both Touch Events (as defined in [[TOUCH-EVENTS]]) and Pointer Events. For more information on the relationship between these two specifications, see theTouch Events Community Group.
The following are basic examples that demonstrate how some of the APIs in this specification might be used by authors. Further, more specific examples are provided in the relevant sections of this document.
/* Bind to either Pointer Events or traditional touch/mouse */if (window.PointerEvent) { // if Pointer Events are supported, only listen to pointer events target.addEventListener("pointerdown", function(e) { // if necessary, apply separate logic based on e.pointerType // for different touch/pen/mouse behavior ... }); ...} else { // traditional touch/mouse event handlers target.addEventListener('touchstart', function(e) { // prevent compatibility mouse events and click e.preventDefault(); ... }); ... target.addEventListener('mousedown', ...); ...}// additional event listeners for keyboard handling...window.addEventListener("pointerdown", detectInputType);function detectInputType(event) { switch(event.pointerType) { case "mouse": /* mouse input detected */ break; case "pen": /* pen/stylus input detected */ break; case "touch": /* touch input detected */ break; default: /* pointerType is empty (could not be detected) or UA-specific custom type */ }}<div></div><script>window.addEventListener("pointerdown", checkPointerSize);function checkPointerSize(event) { event.target.style.width = event.width + "px"; event.target.style.height = event.height + "px";}</script>const event1 = new PointerEvent("pointerover", { bubbles: true, cancelable: true, composed: true, pointerId: 42, pointerType: "pen", clientX: 300, clientY: 500 });eventTarget.dispatchEvent(event1);let pointerEventInitDict ={ bubbles: true, cancelable: true, composed: true, pointerId: 42, pointerType: "pen", clientX: 300, clientY: 500,};const p1 = new PointerEvent("pointermove", pointerEventInitDict);pointerEventInitDict.clientX += 10;const p2 = new PointerEvent("pointermove", pointerEventInitDict);pointerEventInitDict.coalescedEvents = [p1, p2];const event2 = new PointerEvent("pointermove", pointerEventInitDict);eventTarget.dispatchEvent(event2);<div></div> <script> window.addEventListener("pointerdown", assignPenColor); window.addEventListener("pointermove", assignPenColor); const colorMap = new Map(); function assignPenColor(event) { const uniqueId = event.persistentDeviceId; // Check if a unique Id exists. if (uniqueId == 0) { return; } // Check if a color has been assigned to the device. if (map.has(uniqueId)) { return; } // Assign a color to the device. let newColor = getNewColor(); map.set(uniqueId, newColor); return newColor; } function getNewColor() { /* return some color value */ } </script> The mouse event module originates from the [[HTML401]]onclick,ondblclick,onmousedown,onmouseup,onmouseover,onmousemove, andonmouseout attributes. This event module is specifically designed for use with pointing input devices, such as a mouse or a trackball.
Introduced in DOM Level 2, modified in this specification.
The {{MouseEvent}} interface provides specific contextual information associated with Mouse events.
In the case of nested elements, mouse events are always targeted at the most deeply nested element.
Ancestors of the targeted element can use event bubbling to obtain notifications of mouse events which occur within their descendent elements.
To create an instance of the {{MouseEvent}} interface, use the {{MouseEvent}} constructor, passing an optional {{MouseEventInit}} dictionary.
When initializing {{MouseEvent}} objects usinginitMouseEvent,implementations can use the client coordinates {{MouseEvent/clientX}} and {{MouseEvent/clientY}} for calculation of other coordinates (suchas target coordinates exposed by DOM Level 0 implementations orother proprietary attributes, e.g.,pageX).
[Exposed=Window]interface MouseEvent : UIEvent {constructor(DOMString type, optional MouseEventInit eventInitDict = {});readonly attribute long screenX;readonly attribute long screenY;readonly attribute long clientX;readonly attribute long clientY;readonly attribute long layerX;readonly attribute long layerY;readonly attribute boolean ctrlKey;readonly attribute boolean shiftKey;readonly attribute boolean altKey;readonly attribute boolean metaKey;readonly attribute short button;readonly attribute unsigned short buttons;readonly attribute EventTarget? relatedTarget;boolean getModifierState(DOMString keyArg);};The horizontal coordinate at which the event occurred relative to the origin of the screen coordinate system.
The [=un-initialized value=] of this attribute MUST be0.
The vertical coordinate at which the event occurred relative to the origin of the screen coordinate system.
The [=un-initialized value=] of this attribute MUST be0.
The horizontal coordinate at which the event occurred relative to the viewport associated with the event.
The [=un-initialized value=] of this attribute MUST be0.
The vertical coordinate at which the event occurred relative to the viewport associated with the event.
The [=un-initialized value=] of this attribute MUST be0.
The horizontal offset from the nearest [=tree/ancestor=] element which is a [=stacking context=], ispositioned, or paints in the positioned phase whenpainting a stacking context.
The [=un-initialized value=] of this attribute MUST be0.
The vertical offset from the nearest [=tree/ancestor=] element which is a [=stacking context=], ispositioned, or paints in thepositioned phase whenpainting a stacking context.
The [=un-initialized value=] of this attribute MUST be0.
Refer to the {{KeyboardEvent}}'s {{KeyboardEvent/ctrlKey}} attribute.
The [=un-initialized value=] of this attribute MUST befalse.
Refer to the {{KeyboardEvent}}'s {{KeyboardEvent/shiftKey}} attribute.
The [=un-initialized value=] of this attribute MUST befalse.
Refer to the {{KeyboardEvent}}'s {{KeyboardEvent/altKey}} attribute.
The [=un-initialized value=] of this attribute MUST befalse.
Refer to the {{KeyboardEvent}}'s {{KeyboardEvent/metaKey}} attribute.
The [=un-initialized value=] of this attribute MUST befalse.
During mouse events caused by the depression or release of a mouse button, {{MouseEvent/button}} MUST be used to indicate which pointer device button changed state.
The value of the {{MouseEvent/button}} attribute MUST be as follows:
0 MUST indicate the primary button of the device (in general, the left button or the only button on single-button devices, used to activate a user interface control or select text) or the un-initialized value.1 MUST indicate the auxiliary button (in general, the middle button, often combined with a mouse wheel).2 MUST indicate the secondary button (in general, the right button, often used to display a context menu).3 MUST indicate the X1 (back) button.4 MUST indicate the X2 (forward) button. Some pointing devices provide or simulate more button states, and values higher than2 or lower than0 MAY be used to represent such buttons.
The value of {{MouseEvent/button}} is not updated for events not caused by the depression/release of a mouse button. In these scenarios, take care not to interpret the value0 as the left button, but rather as the default value.
Somedefault actions related to events such as {{mousedown}} and {{mouseup}} depend on the specific mouse button in use.
The [=un-initialized value=] of this attribute MUST be0.
During any mouse events, {{MouseEvent/buttons}} MUST be used to indicate which combination of mouse buttons are currently being pressed, expressed as a bitmask.
Though similarly named, the values for the {{MouseEvent/buttons}} attribute and the {{MouseEvent/button}} attribute are very different. The value of {{MouseEvent/button}} is assumed to be valid during {{mousedown}} / {{mouseup}} event handlers, whereas the {{MouseEvent/buttons}} attribute reflects the state of the mouse's buttons for any trusted {{MouseEvent}} object (while it is being dispatched), because it can represent the "no button currently active" state (0).
The value of the {{MouseEvent/buttons}} attribute MUST be as follows:
0 MUST indicate no button is currently active.1 MUST indicate the primary button of the device (in general, the left button or the only button on single-button devices, used to activate a user interface control or select text).2 MUST indicate the secondary button (in general, the right button, often used to display a context menu), if present.4 MUST indicate the auxiliary button (in general, the middle button, often combined with a mouse wheel). Some pointing devices provide or simulate more buttons. To represent such buttons, the value MUST be doubled for each successive button (in the binary series8,16,32, ... ).
Because the sum of any set of button values is a unique number, a content author can use a bitwise operation to determine how many buttons are currently being pressed and which buttons they are, for an arbitrary number of mouse buttons on a device. For example, the value3 indicates that the left and right button are currently both pressed, while the value5 indicates that the left and middle button are currently both pressed.
Somedefault actions related to events such as {{mousedown}} and {{mouseup}} depend on the specific mouse button in use.
The [=un-initialized value=] of this attribute MUST be0.
Used to identify a secondary {{EventTarget}} related to a UI event, depending on the type of event.
The [=un-initialized value=] of this attribute MUST benull.
Queries the state of a modifier using a key value.
Returnstrue if it is a modifier key and the modifier is activated,false otherwise.
dictionary MouseEventInit : EventModifierInit {long screenX = 0;long screenY = 0;long clientX = 0;long clientY = 0;short button = 0;unsigned short buttons = 0;EventTarget? relatedTarget = null;};Initializes the {{MouseEvent/screenX}} attribute of the {{MouseEvent}} object to the desired horizontal relative position of the mouse pointer on the user's screen.
Initializing the event object to the given mouse position must not move the user's mouse pointer to the initialized position.
Initializes the {{MouseEvent/screenY}} attribute of the {{MouseEvent}} object to the desired vertical relative position of the mouse pointer on the user's screen.
Initializing the event object to the given mouse position must not move the user's mouse pointer to the initialized position.
Initializes the {{MouseEvent/clientX}} attribute of the {{MouseEvent}} object to the desired horizontal position of the mouse pointer relative to the client window of the user's browser.
Initializing the event object to the given mouse position must not move the user's mouse pointer to the initialized position.
Initializes the {{MouseEvent/clientY}} attribute of the {{MouseEvent}} object to the desired vertical position of the mouse pointer relative to the client window of the user's browser.
Initializing the event object to the given mouse position must not move the user's mouse pointer to the initialized position.
Initializes the {{MouseEvent/button}} attribute of the {{MouseEvent}} object to a number representing the desired state of the button(s) of the mouse.
The value 0 is used to represent the primary mouse button, 1 is used to represent the auxiliary/middle mouse button, and 2 to represent the right mouse button. Numbers greater than 2 are also possible, but are not specified in this document.
Initializes the {{MouseEvent/buttons}} attribute of the {{MouseEvent}} object to a number representing oneor more of the button(s) of the mouse that are to be considered active.
The {{MouseEvent/buttons}} attribute is a bit-field. If a mask value of 1 is true when applied to the value of the bit field, then the primary mouse button is down. If a mask value of 2 is true when applied to the value of the bit field, then the right mouse button is down. If a mask value of 4 is true when applied to the value of the bit field, then the auxiliary/middle button is down.
In JavaScript, to initialize the {{MouseEvent/buttons}} attribute as if the right (2) and middlebutton (4) were being pressed simultaneously, the buttons value can be assigned as either:
{ buttons: 2 | 4 }or:
{ buttons: 6 }The {{MouseEvent/relatedTarget}} should be initialized to the element whose bounds the mouse pointer just left (in the case of a {{mouseover}} or {{mouseenter}} event) or the element whose bounds the mouse pointer is entering (in the case of a {{mouseout}} or {{mouseleave}} or [=focusout=] event). For other events, this value need not be assigned (and will default to null).
Implementations MUST maintain thecurrent click count when generating mouse events. This MUST be a non-negative integer indicating the number of consecutive clicks of a pointing device button within a specific time. The delay after which the count resets is specific to the environment configuration.
The algorithms in this section assume that the native platform OS will provide the following:
For these events, the OS will be able to provide the following info:
This section needs to be revised.
Generally, when a constructor of an {{Event}} interface, or of an interface inherited from the {{Event}} interface, is invoked, the steps described in [[DOM]] should be followed. However the {{MouseEvent}} interfaces provide additional dictionary members for initializing the internal state of the {{Event}} object's key modifiers: specifically, the internal state queried for using the {{MouseEvent/getModifierState()}} methods. This section supplements the [[DOM]] steps for intializing a new {{MouseEvent}} object with these optional modifier states.
For the purposes of constructing a {{MouseEvent}}, or object derived from these objects using the algorithm below, all {{MouseEvent}}, and derived objects haveinternal key modifier state which can be set and retrieved using thekey modifier names described in theModifier Keys table in [[UIEvents-Key]].
The following steps supplement the algorithm defined for constructing events in [[DOM]]:
"modifier", then let thekey modifier name be the dictionary member's name excluding the prefix"modifier", and set the {{Event}} object's [=internal key modifier state=] that matches the [=key modifier name=] to the corresponding value.This section needs to be revised.
The UA must maintain the following values that are shared for the entire User Agent.
Amouse button bitmask that tracks the current state of the mouse buttons.
The UA must maintain the following values that are shared for the Window.
Alast mouse element value (initially undefined) that keeps track of the last {{Element}} that we sent a MouseEvent to.
Alast mouse DOM path value (initially empty) that contains a snapshot of the ancestors {{Element}}s of thelast mouse element when the most recent mouse event was sent.
This section needs to be revised.
A {{MouseEvent}} has the following internal flags that are used to track the state of various modifier keys:shift flag,control flag,alt flag,altgraph flag,andmeta flag.These flags are set if the corresponding modifier key was pressed at the timeof the mouse event.
This section needs to be revised.
To account forinert ordisabled elements. this should call {{Document/elementsFromPoint()}} and reject invalid elements.
This section needs to be revised.
Toinitialize a MouseEvent with |event|, |eventType| and |eventTarget|, |bubbles|, and |cancelable|, run the following steps:
We should provide a hook for PointerLock instead of hardcoding it here.
This section needs to be revised.
This section needs to be revised.
This section needs to be revised.
This section needs to be revised.
This will return a button ID suitable for storing in the {{MouseEvent}}'s {{MouseEvent/button}} attribute.
This section needs to be revised.
TODO.
This section needs to be revised.
Other buttons can be added starting with 0x08 .
This section needs to be revised.
Other mouse events can occur between the mousedown and mouseup.
This section needs to be revised.
The platform should call this immediately afterhandle native mouse up for mouseups that generate clicks.
This section needs to be revised.
Seepointerevents/100for info about browsers using PointerEvents and rounded coordinates.
Any "default action" is handled during dispatch by triggering theactivation behavioralgorithm for the target. So there is no need for handle that here.However, need to verify that the existing spec handles disabled/css-pointer-events/inert/...
To handle `HTMLelement.click()`, call this algorithm with |native| = null and |target| = `HTMLelement`.
To handle keyboard-initiated clicks, call this algorithm with |native| = null and |target| = currently focused element.
This section needs to be revised.
This should be called immediately after handle native mouse click for mouse clicks that generate double clicks.
This section needs to be revised.
This algorithm makes assumptions about the dispatch of PointerEvents because they are not currently specified explicitly. Oncepointerevents/285 is resolved this may need to be updated.
TODO: Set |mouseout| attributes from |native|. +CSSOM attributes.
Verify behavior when canceled (appears to have no effect).
Handle case where |element| has been deleted.Also case where it has been moved: Should the DOM mutation have triggereda mouseleave event? Should we sent it now? Should it be dropped?Need to verify what current browsers do.
Check compat: Value of event.composed. Spec says false. Chrome/Linux = true. Firefox/Linux = false.
TODO: Set |mouseout| attributes from |native|. +CSSOM attributes.
Need to verify behavior when canceled (appears to have no effect).
Handle case where |element| has been deleted or moved.
Check compat: Value of event.composed. Spec says false.Chrome/Linux = true.Firefox/Linux = false.
Check compat for shadow DOM elements. Chrome/Linux fires this event at the element and the shadow root.
This section needs to be revised.
To handle a context menu triggered by the keyboard, call this algorithm with |native| = null and |target| = currently focused element.
Certain mouse events defined in this specification MUST occur in a set order relative to one another. The following shows the event sequence that MUST occur when a pointing device's cursor is moved over an element:
| # | Event Type | Element | Notes |
|---|---|---|---|
| 1 | {{mousemove}} | ||
| Pointing device is moved into element A... | |||
| 2 | {{mouseover}} | A | |
| 3 | {{mouseenter}} | A | |
| 4 | {{mousemove}} | A | Multiple {{mousemove}} events |
| Pointing device is moved out of element A... | |||
| 5 | {{mouseout}} | A | |
| 6 | {{mouseleave}} | A |
When a pointing device is moved into an elementA, and then into a nested elementB and then back out again, the following sequence of events MUST occur:
| Event Type | Element | Notes | |
|---|---|---|---|
| 1 | {{mousemove}} | ||
| Pointing device is moved into element A... | |||
| 2 | {{mouseover}} | A | |
| 3 | {{mouseenter}} | A | |
| 4 | {{mousemove}} | A | Multiple {{mousemove}} events |
| Pointing device is moved into nested element B... | |||
| 5 | {{mouseout}} | A | |
| 6 | {{mouseover}} | B | |
| 7 | {{mouseenter}} | B | |
| 8 | {{mousemove}} | B | Multiple {{mousemove}} events |
| Pointing device is moved from element B into A... | |||
| 9 | {{mouseout}} | B | |
| 10 | {{mouseleave}} | B | |
| 11 | {{mouseover}} | A | |
| 12 | {{mousemove}} | A | Multiple {{mousemove}} events |
| Pointing device is moved out of element A... | |||
| 13 | {{mouseout}} | A | |
| 14 | {{mouseleave}} | A |
Sometimes elements can be visually overlapped using CSS. In the following example, three elements labeled A, B, and C all have the same dimensions and absolute position on a web page. Element C is a child of B, and B is a child of A in the DOM:
When the pointing device is moved from outside the element stack to the element labeled C and then moved out again, the following series of events MUST occur:
| Event Type | Element | Notes | |
|---|---|---|---|
| 1 | {{mousemove}} | ||
| Pointing device is moved into element C, the topmost element in the stack | |||
| 2 | {{mouseover}} | C | |
| 3 | {{mouseenter}} | A | |
| 4 | {{mouseenter}} | B | |
| 5 | {{mouseenter}} | C | |
| 6 | {{mousemove}} | C | Multiple {{mousemove}} events |
| Pointing device is moved out of element C... | |||
| 7 | {{mouseout}} | C | |
| 8 | {{mouseleave}} | C | |
| 9 | {{mouseleave}} | B | |
| 10 | {{mouseleave}} | A |
The {{mouseover}}/{{mouseout}} events are only fired once, while {{mouseenter}}/{{mouseleave}} events are fired three times (once to each element).
The following is the typical sequence of events when a button associated with a pointing device (e.g., a mouse button or trackpad) is pressed and released over an element:
| Event Type | Notes | |
|---|---|---|
| 1 | {{mousedown}} | |
| 2 | {{mousemove}} | OPTIONAL, multiple events, some limits |
| 3 | {{mouseup}} | |
| 4 | {{click}} | |
| 5 | {{mousemove}} | OPTIONAL, multiple events, some limits |
| 6 | {{mousedown}} | |
| 7 | {{mousemove}} | OPTIONAL, multiple events, some limits |
| 8 | {{mouseup}} | |
| 9 | {{click}} | |
| 10 | {{dblclick}} |
The lag time, degree, distance, and number of {{mousemove}} events allowed between the {{mousedown}} and {{mouseup}} events while still firing a {{click}} or {{dblclick}} event will be implementation-, device-, and platform-specific. This tolerance can aid users that have physical disabilities like unsteady hands when these users interact with a pointing device.
Each implementation will determine the appropriatehysteresistolerance, but in general SHOULD fire {{click}} and {{dblclick}}events when the event target of the associated {{mousedown}} and{{mouseup}} events is the same element with no {{mouseout}} or{{mouseleave}} events intervening, and SHOULD fire {{click}} and{{dblclick}} events on the nearest common inclusive ancestor when theassociated {{mousedown}} and {{mouseup}} event targets aredifferent.
If a {{mousedown}} event was targeted at an HTML document'sbodyelement, and the corresponding {{mouseup}} event was targeted atthedocument element, then the {{click}} event will be dispatchedto thedocument element, since it is the nearest common inclusiveancestor.
If the [=Event/target=] (e.g. the target element) is removed from theDOM during the mouse events sequence, the remaining events of thesequence MUST NOT be fired on that element.
If the target element is removed from the DOM as the result of a{{mousedown}} event, no events for that element will be dispatchedfor {{mouseup}}, {{click}}, or {{dblclick}}, nor any defaultactivation events. However, the {{mouseup}} event will still bedispatched on the element that is exposed to the mouse after the removalof the initial target element. Similarly, if the target element isremoved from the DOM during the dispatch of a {{mouseup}} event, the{{click}} and subsequent events will not be dispatched.
| Type | auxclick |
|---|---|
| Interface | {{PointerEvent}} |
| Sync / Async | Sync |
| Bubbles | Yes |
| Trusted Targets | Element |
| Cancelable | Yes |
| Composed | Yes |
| Default action | Varies |
| Context (trusted events) |
|
The {{auxclick}} event type MUST be dispatched on thetopmostevent target indicated by the pointer, when the user pressesdown and releases the non-primary pointer button, or otherwise activatesthe pointer in a manner that simulates such an action. The actuationmethod of the mouse button depends upon the pointer device and theenvironment configuration, e.g., it MAY depend on the screenlocation or the delay between the press and release of the pointingdevice button.
The {{auxclick}} event should only be fired for the non-primary pointerbuttons (i.e., when {{MouseEvent/button}} value is not0,{{MouseEvent/buttons}} value is greater than1). The primary button(like the left button on a standard mouse) MUST NOT fire{{auxclick}} events. See {{click}} for a corresponding event thatis associated with the primary button.
The {{auxclick}} event MAY be preceded by the {{mousedown}} and{{mouseup}} events on the same element, disregarding changesbetween other node types (e.g., text nodes). Depending upon theenvironment configuration, the {{auxclick}} event MAY be dispatchedif one or more of the event types {{mouseover}},{{mousemove}}, and {{mouseout}} occur between the press andrelease of the pointing device button.
Thedefault action of the {{auxclick}} event type variesbased on the [=Event/target=] of the event and the value of the{{MouseEvent/button}} or {{MouseEvent/buttons}} attributes. Typicaldefault actions of the {{auxclick}} event type are as follows:
myLink.addEventListener("auxclick", function(e) { if (e.button === 1) { // This would prevent the default behavior which is for example // opening a new tab when middle clicking on a link. e.preventDefault(); // Do something else to handle middle button click like taking // care of opening link or non-link buttons in new tabs in a way // that fits the app. Other actions like closing a tab in a tab-strip // which should be done on the click action can be done here too. }});In the case of right button, the {{auxclick}} event is dispatched afterany {{contextmenu}} event. Note that some user agents swallow all inputevents while a context menu is being displayed, so auxclick may not beavailable to applications in such scenarios.See for more clarification.
myDiv.addEventListener("contextmenu", function(e) { // This call makes sure no context menu is shown // to interfere with page receiving the events. e.preventDefault();});myDiv.addEventListener("auxclick", function(e) { if (e.button === 2) { // Do something else to handle right button click like opening a // customized context menu inside the app. }});| Type | click |
|---|---|
| Interface | {{PointerEvent}} |
| Sync / Async | Sync |
| Bubbles | Yes |
| Trusted Targets | Element |
| Cancelable | Yes |
| Composed | Yes |
| Default action | Varies |
| Context (trusted events) |
|
The {{click}} event type MUST be dispatched on thetopmostevent target indicated by the pointer, when the user pressesdown and releases the primary pointer button, or otherwise activatesthe pointer in a manner that simulates such an action. The actuationmethod of the mouse button depends upon the pointer device and theenvironment configuration, e.g., it MAY depend on the screenlocation or the delay between the press and release of the pointingdevice button.
The {{click}} event should only be fired for the primary pointerbutton (i.e., when {{MouseEvent/button}} value is0,{{MouseEvent/buttons}} value is1). Secondary buttons(like the middle or right button on a standard mouse) MUST NOT fire{{click}} events. See {{auxclick}} for a corresponding event thatis associated with the non-primary buttons.
The {{click}} event MAY be preceded by the {{mousedown}} and{{mouseup}} events on the same element, disregarding changesbetween other node types (e.g., text nodes). Depending upon theenvironment configuration, the {{click}} event MAY be dispatchedif one or more of the event types {{mouseover}},{{mousemove}}, and {{mouseout}} occur between the press andrelease of the pointing device button. The {{click}} event MAYalso be followed by the {{dblclick}} event.
If a user mouses down on a text node child of a<p> element which has been styled with a largeline-height, shifts the mouse slightly such that it is no longerover an area containing text but is still within the containingblock of that<p> element (i.e., the pointer isbetween lines of the same text block, but not over the text node perse), then subsequently mouses up, this will likely still trigger a{{click}} event (if it falls within the normal temporalhysteresis for a {{click}}), since the user has stayedwithin the scope of the same element. Note that user-agent-generatedmouse events are not dispatched on text nodes.
In addition to being associated with pointer devices, the{{click}} event type MUST be dispatched as part of an elementactivation.
For maximum accessibility, content authors are encouraged to use the{{click}} event type when defining activation behavior for customcontrols, rather than other pointing-device event types such as{{mousedown}} or {{mouseup}}, which are more device-specific.Though the {{click}} event type has its origins in pointerdevices (e.g., a mouse), subsequent implementation enhancements haveextended it beyond that association, and it can be considered adevice-independent event type for element activation.
Thedefault action of the {{click}} event type variesbased on the [=Event/target=] of the event and the value of the{{MouseEvent/button}} or {{MouseEvent/buttons}} attributes. Typicaldefault actions of the {{click}} event type are as follows:
| Type | contextmenu |
|---|---|
| Interface | {{PointerEvent}} |
| Sync / Async | Sync |
| Bubbles | Yes |
| Trusted Targets | Element |
| Cancelable | Yes |
| Composed | Yes |
| Default action | Invoke a context menu if supported. |
| Context (trusted events) |
|
Auser agent MUST dispatch this event before invoking a context menu.
When the {{contextmenu}} event is triggered by right mouse button, the{{contextmenu}} event MUST be dispatched after the {{mousedown}} event.
Depending on the platform, the {{contextmenu}} event may be dispatchedbefore or after the {{mouseup}} event.
| Type | dblclick |
|---|---|
| Interface | {{MouseEvent}} |
| Sync / Async | Sync |
| Bubbles | Yes |
| Trusted Targets | Element |
| Cancelable | Yes |
| Composed | Yes |
| Default action | None |
| Context (trusted events) |
|
Auser agent MUST dispatch this event when the primary buttonof a pointing device is clicked twice over an element. Thedefinition of a double click depends on the environmentconfiguration, except that the event target MUST be the same between{{mousedown}}, {{mouseup}}, and {{dblclick}}. This eventtype MUST be dispatched after the event type {{click}} if a clickand double click occur simultaneously, and after the event type{{mouseup}} otherwise.
As with the {{click}} event, the {{dblclick}} event shouldonly be fired for the primary pointer button. Secondary buttons MUSTNOT fire {{dblclick}} events.
Canceling the {{click}} event does not affect the firing of a{{dblclick}} event.
As with the {{click}} event type, thedefault action ofthe {{dblclick}} event type varies based on the [=Event/target=] of the event and the value of the {{MouseEvent/button}}or {{MouseEvent/buttons}} attributes. The typicaldefault actions of the {{dblclick}} event type match thoseof the {{click}} event type.| Type | mousedown |
|---|---|
| Interface | {{MouseEvent}} |
| Sync / Async | Sync |
| Bubbles | Yes |
| Trusted Targets | Element |
| Cancelable | Yes |
| Composed | Yes |
| Default action | Varies: Start a drag/drop operation; start a text selection; start a scroll/pan interaction (in combination with the middle mouse button, if supported) |
| Context (trusted events) |
|
Many implementations use the {{mousedown}} event to begin avariety of contextually dependentdefault actions. Thesedefault actions can be prevented if this event is canceled. Some ofthese default actions could include: beginning a drag/dropinteraction with an image or link, starting text selection, etc.Additionally, some implementations provide a mouse-driven panningfeature that is activated when the middle mouse button is pressed atthe time the {{mousedown}} event is dispatched.
| Type | mouseenter |
|---|---|
| Interface | {{MouseEvent}} |
| Sync / Async | Sync |
| Bubbles | No |
| Trusted Targets | Element |
| Cancelable | No |
| Composed | No |
| Default action | None |
| Context (trusted events) |
|
There are similarities between this event type and the CSS:hover pseudo-class [[CSS2]].See also the {{mouseleave}} event type.
| Type | mouseleave |
|---|---|
| Interface | {{MouseEvent}} |
| Sync / Async | Sync |
| Bubbles | No |
| Trusted Targets | Element |
| Cancelable | No |
| Composed | No |
| Default action | None |
| Context (trusted events) |
|
There are similarities between this event type and the CSS:hover pseudo-class [[CSS2]].See also the {{mouseenter}} event type.
| Type | mousemove |
|---|---|
| Interface | {{MouseEvent}} |
| Sync / Async | Sync |
| Bubbles | Yes |
| Trusted Targets | Element |
| Cancelable | Yes |
| Composed | Yes |
| Default action | None |
| Context (trusted events) |
|
In some implementation environments, such as a browser,{{mousemove}} events can continue to fire if the user began adrag operation (e.g., a mouse button is pressed) and the pointingdevice has left the boundary of the user agent.
This event was formerly specified to be non-cancelable in DOM Level2 Events, but was changed to reflect existing interoperability betweenuser agents.
| Type | mouseout |
|---|---|
| Interface | {{MouseEvent}} |
| Sync / Async | Sync |
| Bubbles | Yes |
| Trusted Targets | Element |
| Cancelable | Yes |
| Composed | Yes |
| Default action | None |
| Context (trusted events) |
|
See also the {{mouseover}} event type.
| Type | mouseover |
|---|---|
| Interface | {{MouseEvent}} |
| Sync / Async | Sync |
| Bubbles | Yes |
| Trusted Targets | Element |
| Cancelable | Yes |
| Composed | Yes |
| Default action | None |
| Context (trusted events) |
|
See also the {{mouseout}} event type.
| Type | mouseup |
|---|---|
| Interface | {{MouseEvent}} |
| Sync / Async | Sync |
| Bubbles | Yes |
| Trusted Targets | Element |
| Cancelable | Yes |
| Composed | Yes |
| Default action | None |
| Context (trusted events) |
|
In some implementation environments, such as a browser, a{{mouseup}} event can be dispatched even if the pointing devicehas left the boundary of the user agent, e.g., if the user began adrag operation with a mouse button pressed.
PointerEvent interfacedictionary PointerEventInit : MouseEventInit { long pointerId = 0; double width = 1; double height = 1; float pressure = 0; float tangentialPressure = 0; long tiltX; long tiltY; long twist = 0; double altitudeAngle; double azimuthAngle; DOMString pointerType = ""; boolean isPrimary = false; long persistentDeviceId = 0; sequence<PointerEvent> coalescedEvents = []; sequence<PointerEvent> predictedEvents = [];};[Exposed=Window]interface PointerEvent : MouseEvent { constructor(DOMString type, optional PointerEventInit eventInitDict = {}); readonly attribute long pointerId; readonly attribute double width; readonly attribute double height; readonly attribute float pressure; readonly attribute float tangentialPressure; readonly attribute long tiltX; readonly attribute long tiltY; readonly attribute long twist; readonly attribute double altitudeAngle; readonly attribute double azimuthAngle; readonly attribute DOMString pointerType; readonly attribute boolean isPrimary; readonly attribute long persistentDeviceId; [SecureContext] sequence<PointerEvent> getCoalescedEvents(); sequence<PointerEvent> getPredictedEvents();};A unique identifier for the pointer causing the event.user agents MAY reserve a generic {{pointerId}} value of0 or1 for the primary mouse pointer. The {{pointerId}} value of-1 MUST be reserved and used to indicate events that were generated by something other than a pointing device. For any other pointers, user agents are free to implement different strategies and approaches in how they assign a {{pointerId}} value. However, allactive pointers in the [=top-level browsing context=] (as defined by [[HTML]]) must be unique, and the identifier MUST NOT be influenced by any other top-level browsing context (i.e. one top-level browsing context cannot assume that the {{pointerId}} of a pointer will be the same when the pointer moves outside of the browsing context and into another top-level browsing context).
Theuser agent MAY recycle previously retired values for {{pointerId}} from previous active pointers, or it MAY always reuse the same {{pointerId}} for a particular pointing device (for instance, to uniquely identify particular pen/stylus inputs from a specific user in a multi-user collaborative application). However, in the latter case, to minimize the chance of fingerprinting and tracking across different pages or domains, the {{pointerId}} MUST only be associated explicitly with that particular pointing device for the lifetime of the page / session, and a new randomized {{pointerId}} MUST be chosen the next time that particular pointing device is used again in a new session.
The {{pointerId}} selection algorithm is implementation specific. Authors cannot assume values convey any particular meaning other than an identifier for the pointer that is unique from all other active pointers. As an example, user agents may simply assign a number, starting from0, to any active pointers, in the order that they become active — but these values are not guaranteed to be monotonically increasing. As the reuse of the same {{pointerId}} for a particular pointing device is left up to individual implementations, authors are strongly discouraged from relying on it, and to refer to {{persistentDeviceId}} instead.
The width (magnitude on the X axis), in CSS pixels (see [[CSS21]]), of thecontact geometry of the pointer. This value MAY be updated on each event for a given pointer. For inputs that typically lack contact geometry (such as a traditional mouse), and in cases where the actual geometry of the input is not detected by the hardware, theuser agent MUST return a default value of1.
The height (magnitude on the Y axis), in CSS pixels (see [[CSS21]]), of thecontact geometry of the pointer. This value MAY be updated on each event for a given pointer. For inputs that typically lack contact geometry (such as a traditional mouse), and in cases where the actual geometry of the input is not detected by the hardware, theuser agent MUST return a default value of1.
The normalized pressure of the pointer input in the range of[0,1], where0 and1 represent the minimum and maximum pressure the hardware is capable of detecting, respectively. For hardware and platforms that do not support pressure, the value MUST be0.5 when in theactive buttons state and0 otherwise.
The normalized tangential pressure (also known as barrel pressure), typically set by an additional control (e.g. a finger wheel on an airbrush stylus), of the pointer input in the range of[-1,1], where0 is the neutral position of the control. Note that some hardware may only support positive values in the range of[0,1]. For hardware and platforms that do not support tangential pressure, the value MUST be0.
The plane angle (in degrees, in the range of[-90,90]) between the Y-Z plane and the plane containing both the transducer (e.g. pen/stylus) axis and the Y axis. A positivetiltX is to the right, in the direction of increasing X values.tiltX can be used along withtiltY to represent the tilt away from the normal of a transducer with the digitizer. For hardware and platforms that do not report tilt or angle, the value MUST be0.

tiltX.The plane angle (in degrees, in the range of[-90,90]) between the X-Z plane and the plane containing both the transducer (e.g. pen/stylus) axis and the X axis. A positivetiltY is towards the user, in the direction of increasing Y values.tiltY can be used along withtiltX to represent the tilt away from the normal of a transducer with the digitizer. For hardware and platforms that do not report tilt or angle, the value MUST be0.

tiltY.The clockwise rotation (in degrees, in the range of[0,359]) of a transducer (e.g. pen/stylus) around its own major axis. For hardware and platforms that do not report twist, the value MUST be0.
The altitude (in radians) of the transducer (e.g. pen/stylus), in the range[0,π/2] — where0 is parallel to the surface (X-Y plane), andπ/2 is perpendicular to the surface. For hardware and platforms that do not report tilt or angle, the value MUST beπ/2.
altitudeAngle isπ/2, which positions the transducer as being perpendicular to the surface. This differs from theTouch Events - Level 2 specification's definition for thealtitudeAngle property, which has a default value of0.
altitudeAngle ofπ/4 (45 degrees from the X-Y plane).The azimuth angle (in radians) of the transducer (e.g. pen/stylus), in the range[0, 2π] — where0 represents a transducer whose cap is pointing in the direction of increasing X values (point to "3 o'clock" if looking straight down) on the X-Y plane, and the values progressively increase when going clockwise (π/2 at "6 o'clock",π at "9 o'clock",3π/2 at "12 o'clock"). When the transducer is perfectly perpendicular to the surface (altitudeAngle ofπ/2), the value MUST be0. For hardware and platforms that do not report tilt or angle, the value MUST be0.

azimuthAngle ofπ/6 ("4 o'clock").Indicates the device type that caused the event (such as mouse, pen, touch). If the user agent is tofire a pointer event for a mouse, pen/stylus, or touch input device, then the value ofpointerType MUST be according to the following table:
| Pointer Device Type | pointerType Value |
|---|---|
| Mouse | mouse |
| Pen / stylus | pen |
| Touch contact | touch |
If the device type cannot be detected by the user agent, then the value MUST be an empty string. If the user agent supports pointer device types other than those listed above, the value ofpointerType SHOULD be vendor prefixed to avoid conflicting names for different types of devices. Future specifications MAY provide additional normative values for other device types.
pointerType can be used. Also note that developers should include some form of default handling to cover user agents that may have implemented their own custompointerType values and for situations wherepointerType is simply an empty string.Indicates if the pointer represents theprimary pointer of this pointer type.
A unique identifier for the pointing device. If the hardware supports multiple pointers, pointer events generated from pointing devices MUST only get apersistentDeviceId if those pointers are uniquely identifiable over the session. If the pointer is uniquely identifiable, the assignedpersistentDeviceId to that pointing device will remain constant for the remainder of the session. ThepersistentDeviceId value of0 MUST be reserved and used to indicate events whose generating device could not be identified. LikepointerId, to minimize the chance of fingerprinting and tracking across different pages or domains, thepersistentDeviceId MUST only be associated explicitly with that particular pointing device for the lifetime of the page / session, and a new randomizedpersistentDeviceId MUST be chosen the next time that particular pointing device is used again in a new session.
persistentDeviceId is not guaranteed to be available for all pointer events from a pointing device. For example, the device may not report its hardware id to the digitizer in time forpointerdown to have apersistentDeviceId. In such a case, thepersistentDeviceId may initially be0 and change to a valid value.A method that returns the list ofcoalesced events.
A method that returns the list ofpredicted events.
ThePointerEventInit dictionary is used by the {{PointerEvent}} interface's constructor to provide a mechanism by which to construct untrusted (synthetic) pointer events. It inherits from the {{MouseEventInit}} dictionary defined in [[UIEVENTS]]. See theexamples for sample code demonstrating how to fire an untrusted pointer event.
The [=event constructing steps=] forPointerEvent clones {{PointerEventInit}}'s {{PointerEventInit/coalescedEvents}} tocoalesced events list and clones {{PointerEventInit}}'s {{PointerEventInit/predictedEvents}} topredicted events list.
PointerEvent interface inherits from {{MouseEvent}}, defined in [[[UIEVENTS]]]. Also note the proposed extension in [[[CSSOM-VIEW]]], which changes the various coordinate properties fromlong todouble to allow for fractional coordinates. For user agents that already implement this proposed extension for {{PointerEvent}}, butnot for regular {{MouseEvent}}, there are additional requirements when it comes to theclick,auxclick, andcontextmenu events.Some pointer devices, such as mouse or pen, support multiple buttons. In the [[UIEVENTS]] Mouse Event model, each button press produces amousedown andmouseup event. To better abstract this hardware difference and simplify cross-device input authoring, Pointer Events do not fire overlapping {{pointerdown}} and {{pointerup}} events for chorded button presses (depressing an additional button while another button on the pointer device is already depressed).
Instead, chorded button presses can be detected by inspecting changes to thebutton andbuttons properties. Thebutton andbuttons properties are inherited from the {{MouseEvent}} interface, but with a change in semantics and values, as outlined in the following sections.
The modifications to thebutton andbuttons properties apply only to pointer events. However forclick,auxclick andcontextmenu the value ofbutton andbuttons MUST follow [[UIEVENTS]], as is the case forcompatibility mouse events .
button propertyTo identify button state transitions in any pointer event (and not just {{pointerdown}} and {{pointerup}}), thebutton property indicates the device button whose state change fired the event.
| Device Button Changes | button |
|---|---|
| Neither buttons nor touch/pen contact changed since last event | -1 |
| Left Mouse, Touch contact, Pen contact | 0 |
| Middle Mouse | 1 |
| Right Mouse, Pen barrel button | 2 |
| X1 (back) Mouse | 3 |
| X2 (forward) Mouse | 4 |
| Pen eraser button | 5 |
button property in a {{pointermove}} event will be different from that in amousemove event. For example, while moving the mouse with the right button pressed, the {{pointermove}} events will have thebutton value -1, but themousemove events will have thebutton value 2.buttons propertyThebuttons property gives the current state of the device buttons as a bitmask (same as inMouseEvent, but with an expanded set of possible values).
| Current state of device buttons | buttons |
|---|---|
| Mouse moved with no buttons pressed, Pen moved while hovering with no buttons pressed | 0 |
| Left Mouse, Touch contact, Pen contact | 1 |
| Middle Mouse | 4 |
| Right Mouse, Pen barrel button | 2 |
| X1 (back) Mouse | 8 |
| X2 (forward) Mouse | 16 |
| Pen eraser button | 32 |
In a multi-pointer (e.g. multi-touch) scenario, theisPrimary property is used to identify a master pointer amongst the set ofactive pointers for each pointer type.
pointerType) are considered primary. For example, a touch contact and a mouse cursor moved simultaneously will produce pointers that are both considered primary.false forisPrimary.PointerEvent interfaceTofire a pointer event named |e| means to [=fire an event=] named |e| usingPointerEvent whose attributes are set as defined in {{PointerEvent}} Interface andAttributes and Default Actions.
If the event is not a {{gotpointercapture}}, {{lostpointercapture}},click,auxclick orcontextmenu event, run theprocess pending pointer capture steps for thisPointerEvent.
Determine the target at which the event is fired as follows:
Let |targetDocument| be target's [=Node/node document=] [[DOM]].
If the event is {{pointerdown}}, {{pointermove}}, or {{pointerup}}, setactive document for the event's {{PointerEvent/pointerId}} to |targetDocument|.
If the event is {{pointerdown}}, the associated device is a direct manipulation device, and the target is an {{Element}}, thenset pointer capture for this {{PointerEvent/pointerId}} to the target element as described inimplicit pointer capture.
Before firing this event, theuser agent SHOULD treat the target as if the pointing device has moved over it from the |previousTarget| for the purpose ofensuring event ordering [[UIEVENTS]]. If the |needsOverEvent| flag is set, a {{pointerover}} event is needed even if the target element is the same.
Fire the event to the determined target.
Save the determined target as the |previousTarget| for the given pointer, and reset the |needsOverEvent| flag tofalse. If the |previousTarget| at any point will no longer be [=connected=] [[DOM]], update the |previousTarget| to the nearest still [=connected=] [[DOM]] parent following the event path corresponding to dispatching events to the |previousTarget|, and set the |needsOverEvent| flag totrue.
Thebubbles andcancelable properties and the default actions for the event types defined in this specification appear in the following table. Details of each of these event types are provided inPointer Event types.
| Event Type | Bubbles | Cancelable | Default Action |
|---|---|---|---|
| {{pointerover}} | Yes | Yes | None |
| {{pointerenter}} | No | No | None |
| {{pointerdown}} | Yes | Yes | Varies: when the pointer is primary, all default actions of themousedown eventCanceling this event also prevents subsequent firing ofcompatibility mouse events. |
| {{pointermove}} | Yes | Yes | Varies: when the pointer is primary, all default actions ofmousemove |
| {{pointerrawupdate}} | Yes | No | None |
| {{pointerup}} | Yes | Yes | Varies: when the pointer is primary, all default actions ofmouseup |
| {{pointercancel}} | Yes | No | None |
| {{pointerout}} | Yes | Yes | None |
| {{pointerleave}} | No | No | None |
| {{gotpointercapture}} | Yes | No | None |
| {{lostpointercapture}} | Yes | No | None |
Viewport manipulations (panning and zooming) — generally, as a result of adirect manipulation interaction — are intentionally NOT a default action of pointer events, meaning that these behaviors (e.g. panning a page as a result of moving a finger on a touchscreen) cannot be suppressed by canceling a pointer event. Authors must instead usetouch-action to explicitlydeclare the direct manipulation behavior for a region of the document. Removing this dependency on the cancelation of events facilitates performance optimizations by the user agent.
For {{pointerenter}} and {{pointerleave}} events, the {{EventInit/composed}} [[DOM]] attribute SHOULD befalse; for all other pointer events in the table above, the attribute SHOULD betrue.
For all pointer events in the table above, the {{UIEvent/detail}} [[UIEVENTS]] attribute SHOULD be 0.
fromElement andtoElement in MouseEvents to support legacy content. We encourage those user agents to set the values of those (inherited) attributes in PointerEvents tonull to transition authors to the use of standardized alternates (target andrelatedTarget).Similar toMouseEvent {{MouseEventInit/relatedTarget}}, therelatedTarget should be initialized to the element whose bounds the pointer just left (in the case of a {{pointerover}} orpointerenter event) or the element whose bounds the pointer is entering (in the case of a {{pointerout}} or {{pointerleave}}). For other pointer events, this value will default to null. Note that when an element receives the pointer capture all the following events for that pointer are considered to be inside the boundary of the capturing element.
For {{gotpointercapture}} and {{lostpointercapture}} events, all the attributes except the ones defined in the table above should be the same as the Pointer Event that caused the user agent to run theprocess pending pointer capture steps and fire the {{gotpointercapture}} and {{lostpointercapture}} events.
Theuser agent MUST run the following steps whenimplicitly releasing pointer capture as well as when firing Pointer Events that are not {{gotpointercapture}} or {{lostpointercapture}}.
As defined in the section forclick,auxclick, andcontextmenu events, even after the {{lostpointercapture}} event has been dispatched, the correspondingclick,auxclick orcontextmenu event, if any, would still be dispatched to the capturing target.
Theuser agent MUSTsuppress a pointer event stream when it detects that the web page is unlikely to continue to receive pointer events with a specific {{PointerEvent/pointerId}}. Any of the following scenarios satisfy this condition (there MAY be additional scenarios):
Other scenarios in which theuser agent MAYsuppress a pointer event stream include:
Methods for detecting any of these scenarios are out of scope for this specification.
Theuser agent MUST run the following steps tosuppress a pointer event stream:
A pointing device that moved relative to the screen surface or underwent some change in any of its properties fires various events as defined inPointer Event types. For a stationary pointing device (that neither moved relative to the screen surface nor underwent any change in any properties), theuser agent MUST fire certain boundary events after a layout change that affected thehit test target for the pointer, see {{pointerover}}, {{pointerenter}}, {{pointerout}} and {{pointerleave}} for details. Theuser agent MAY delay the firing of these boundary events because of performance reasons (e.g. to avoid too many hit-tests or layout changes caused by boundary event listeners).
tiltX /tiltY andaltitudeAngle /azimuthAnglePointer Events include two complementary sets of attributes to express the orientation of a transducer relative to the X-Y plane:tiltX /tiltY (introduced in the original Pointer Events specification), andazimuthAngle /altitudeAngle (adopted from theTouch Events - Level 2 specification).
Depending on the specific hardware and platform, user agents will likely only receive one set of values for the transducer orientation relative to the screen plane — eithertiltX /tiltY oraltitudeAngle /azimuthAngle. User agents MUST use the following algorithm for converting these values.
When the user agent calculatestiltX /tiltY fromazimuthAngle /altitudeAngle it SHOULD round the final integer values usingMath.round [[ECMASCRIPT]] rules.
/* Converting between tiltX/tiltY and altitudeAngle/azimuthAngle */function spherical2tilt(altitudeAngle, azimuthAngle) { const radToDeg = 180/Math.PI; let tiltXrad = 0; let tiltYrad = 0; if (altitudeAngle == 0) { // the pen is in the X-Y plane if (azimuthAngle == 0 || azimuthAngle == 2*Math.PI) { // pen is on positive X axis tiltXrad = Math.PI/2; } if (azimuthAngle == Math.PI/2) { // pen is on positive Y axis tiltYrad = Math.PI/2; } if (azimuthAngle == Math.PI) { // pen is on negative X axis tiltXrad = -Math.PI/2; } if (azimuthAngle == 3*Math.PI/2) { // pen is on negative Y axis tiltYrad = -Math.PI/2; } if (azimuthAngle>0 && azimuthAngle<Math.PI/2) { tiltXrad = Math.PI/2; tiltYrad = Math.PI/2; } if (azimuthAngle>Math.PI/2 && azimuthAngle<Math.PI) { tiltXrad = -Math.PI/2; tiltYrad = Math.PI/2; } if (azimuthAngle>Math.PI && azimuthAngle<3*Math.PI/2) { tiltXrad = -Math.PI/2; tiltYrad = -Math.PI/2; } if (azimuthAngle>3*Math.PI/2 && azimuthAngle<2*Math.PI) { tiltXrad = Math.PI/2; tiltYrad = -Math.PI/2; } } if (altitudeAngle != 0) { const tanAlt = Math.tan(altitudeAngle); tiltXrad = Math.atan(Math.cos(azimuthAngle) / tanAlt); tiltYrad = Math.atan(Math.sin(azimuthAngle) / tanAlt); } return {"tiltX":tiltXrad*radToDeg, "tiltY":tiltYrad*radToDeg};}function tilt2spherical(tiltX, tiltY) { const tiltXrad = tiltX * Math.PI/180; const tiltYrad = tiltY * Math.PI/180; // calculate azimuth angle let azimuthAngle = 0; if (tiltX == 0) { if (tiltY > 0) { azimuthAngle = Math.PI/2; } else if (tiltY < 0) { azimuthAngle = 3*Math.PI/2; } } else if (tiltY == 0) { if (tiltX < 0) { azimuthAngle = Math.PI; } } else if (Math.abs(tiltX) == 90 || Math.abs(tiltY) == 90) { // not enough information to calculate azimuth azimuthAngle = 0; } else { // Non-boundary case: neither tiltX nor tiltY is equal to 0 or +-90 const tanX = Math.tan(tiltXrad); const tanY = Math.tan(tiltYrad); azimuthAngle = Math.atan2(tanY, tanX); if (azimuthAngle < 0) { azimuthAngle += 2*Math.PI; } } // calculate altitude angle let altitudeAngle = 0; if (Math.abs(tiltX) == 90 || Math.abs(tiltY) == 90) { altitudeAngle = 0 } else if (tiltX == 0) { altitudeAngle = Math.PI/2 - Math.abs(tiltYrad); } else if (tiltY == 0) { altitudeAngle = Math.PI/2 - Math.abs(tiltXrad); } else { // Non-boundary case: neither tiltX nor tiltY is equal to 0 or +-90 altitudeAngle = Math.atan(1.0/Math.sqrt(Math.pow(Math.tan(tiltXrad),2) + Math.pow(Math.tan(tiltYrad),2))); } return {"altitudeAngle":altitudeAngle, "azimuthAngle":azimuthAngle};}Toinitialize a PointerEvent with |event|, |eventType| and |eventTarget|, |bubbles|, and |cancelable|, run the following steps:
Tocreate a {{PointerEvent}} with |eventType| and |eventTarget|, |bubbles|, and |cancelable|, run the following steps:
TODO.
TODO.
TODO.
TODO.
Can this send pointermove and pointerrawupdate? Or do we need 2 methods?
What is needed to properly define how pointermove events are coalesced?
TODO.
Unlikemousedown events, {{pointerdown}} events are not nested when multiple buttons are pressed. The {{MouseEvent}} is passed so that the fields can be copied into the PointerEvent.
TODO.
Unlikemouseup events, {{pointerup}} events are not nested when multiple buttons are pressed. The {{MouseEvent}} is passed so that the fields can be copied into the PointerEvent.
TODO.
Below are the event types defined in this specification.
In the case of theprimary pointer, these events (with the exception of {{gotpointercapture}} and {{lostpointercapture}}) may also firecompatibility mouse events.
Theuser agent MUSTfire a pointer event named {{pointerover}} when any of the following occurs:
Theuser agent MUSTfire a pointer event named {{pointerenter}} when any of the following occurs:
mouseenter event described in [[UIEVENTS]], and the CSS:hover pseudo-class described in [[CSS21]]. See also the {{pointerleave}} event.Theuser agent MUSTfire a pointer event named {{pointerdown}} when a pointer enters theactive buttons state. For mouse, this is when the device transitions from no buttons depressed to at least one button depressed. For touch, this is when physical contact is made with thedigitizer. For pen, this is when the pen either makes physical contact with the digitizer without any button depressed, or transitions from no buttons depressed to at least one button depressed while hovering.
mousedown andmouseup. Seechorded buttons for more information.For inputdevices that do not support hover, theuser agent MUST alsofire a pointer event named {{pointerover}} followed by a pointer event named {{pointerenter}} prior to dispatching the {{pointerdown}} event.
isPrimary property istrue). This sets thePREVENT MOUSE EVENT flag on the pointer. Note, however, that this does not prevent themouseover,mouseenter,mouseout, ormouseleave events from firing.Theuser agent MUSTfire a pointer event named {{pointermove}} when a pointer changes any properties that don't fire {{pointerdown}} or {{pointerup}} events. This includes any changes to coordinates, pressure, tangential pressure, tilt, twist, contact geometry (width andheight) orchorded buttons.
User agents MAY delay dispatch of the {{pointermove}} event (for instance, for performance reasons). Thecoalesced events information will be exposed via the{{PointerEvent/getCoalescedEvents}} method for the single dispatched {{pointermove}} event. The final coordinates of such events should be used for finding the target of the event.
Theuser agent MUSTfire a pointer event named {{pointerrawupdate}}, and only do so within a [=secure context=], when a pointer changes any properties that don't firepointerdown orpointerup events. Seepointermove event for a list of such properties.
In contrast with {{pointermove}}, user agents SHOULD dispatch {{pointerrawupdate}} events as soon as possible and as frequently as the JavaScript can handle the events.
Thetarget of {{pointerrawupdate}} events might be different from the {{pointermove}} events due to the fact that {{pointermove}} events might get delayed or coalesced, and the final position of the event which is used for finding thetarget could be different from its coalesced events.
Note that if there is already another {{pointerrawupdate}} with the same {{PointerEvent/pointerId}} that hasn't been dispatched in the [=event loop=], theuser agent MAY coalesce the new {{pointerrawupdate}} with that event instead of creating a new [=task=]. This may cause {{pointerrawupdate}} to have coalesced events, and they will all be delivered ascoalesced events of one {{pointerrawupdate}} event as soon as the event is processed in the [=event loop=]. See{{PointerEvent/getCoalescedEvents}} for more information.
In terms of ordering of {{pointerrawupdate}} and {{pointermove}}, if the user agent received an update from the platform that causes both {{pointerrawupdate}} and {{pointermove}} events, then theuser agent MUST dispatch the {{pointerrawupdate}} event before the corresponding {{pointermove}}.
Other than thetarget, the concatenation of coalesced events lists of all dispatched {{pointerrawupdate}} events since the last {{pointermove}} event is the same as the coalesced events of the next {{pointermove}} event in terms of the other event attributes. The attributes of {{pointerrawupdate}} are mostly the same as {{pointermove}}, with the exception ofcancelable which MUST be false for {{pointerrawupdate}}.
User agents SHOULD not firecompatibility mouse events for {{pointerrawupdate}}.
Theuser agent MUSTfire a pointer event named {{pointerup}} when a pointer leaves theactive buttons state. For mouse, this is when the device transitions from at least one button depressed to no buttons depressed. For touch, this is when physical contact is removed from thedigitizer. For pen, this is when the pen is removed from the physical contact with the digitizer while no button is depressed, or transitions from at least one button depressed to no buttons depressed while hovering.
For inputdevices that do not support hover, theuser agent MUST alsofire a pointer event named {{pointerout}} followed by a pointer event named {{pointerleave}} after dispatching the {{pointerup}} event.
All {{pointerup}} events have apressure value of0.
Theuser agent MUST alsoimplicitly release the pointer capture if the pointer is currently captured.
mousedown andmouseup. Seechorded buttons for more information.Theuser agent MUSTfire a pointer event named {{pointercancel}} when it detects a scenario tosuppress a pointer event stream.
The values of the following properties of the {{pointercancel}} event MUST match the values of the last dispatched pointer event with the same {{PointerEvent/pointerId}}:width,height,pressure,tangentialPressure,tiltX,tiltY,twist,altitudeAngle,azimuthAngle,pointerType,isPrimary, and the coordinates inherited from [[UIEVENTS]]. ThecoalescedEvents andpredictedEvents lists in the {{pointercancel}} event MUST be empty, and the event's {{Event/cancelable}} attribute MUST be false.
Theuser agent MUSTfire a pointer event named {{pointerout}} when any of the following occurs:
Theuser agent MUSTfire a pointer event named {{pointerleave}} when any of the following occurs:
mouseleave event described in [[UIEVENTS]], and the CSS:hover pseudo-class described in [[CSS21]]. See also the {{pointerenter}} event.Theuser agent MUSTfire a pointer event named {{gotpointercapture}} when an element receives pointer capture. This event is fired at the element that is receiving pointer capture. Subsequent events for that pointer will be fired at this element. See thesetting pointer capture andprocess pending pointer capture sections.
Theuser agent MUSTfire a pointer event named {{lostpointercapture}} after pointer capture is released for a pointer. This event MUST be fired prior to any subsequent events for the pointer after capture was released. This event is fired at the element from which pointer capture was removed. All subsequent events for the pointer exceptclick,auxclick, andcontextmenu events follow normal hit testing mechanisms (out of scope for this specification) for determining the event target. See thereleasing pointer capture,implicit release of pointer capture, andprocess pending pointer capture sections.
click,auxclick, andcontextmenu eventsThis section is an addition toclick,auxclick andcontextmenu events defined in [[UIEVENTS]]. These events are typically tied to user interface activation, and are fired even from non-pointer input devices, such as keyboards.
These events MUST be of typePointerEvent, and are subject to the additional requirements mentioned in the rest of this section.
For these events, allPointerEvent specific attributes (defined in this spec) other than {{PointerEvent/pointerId}} andpointerType MUST have their default values. In addition:
pointerType MUST be the same as the PointerEvents that caused these events.-1 andpointerType MUST be an empty string.As noted in {{PointerEvent}}, [[[CSSOM-VIEW]]] proposes to redefine the various coordinate properties (screenX,screenY,pageX,pageY,clientX,clientY,x,y,offsetX,offsetY) asdouble, to allow for fractional coordinates. However, this change — when applied only to {{PointerEvent}}, but not to regular {{MouseEvent}} — has proven to lead to web compatibility issues with legacy code in the case ofclick,auxclick, andcontextmenu. For this reason, user agents that have implemented the proposed change in [[[CSSOM-VIEW]]] only for {{PointerEvent}} MUST convert the various coordinate properties for theclick,auxclick, andcontextmenu tolong values (as defined in the original [[[UIEVENTS]]]) usingMath.floor [[ECMASCRIPT]].
Aclick,auxclick orcontextmenu event MUST follow the dispatch process defined in the [[UIEVENTS]] spec except that the event target is overridden using the algorithm below:
Let |event| be theclick,auxclick orcontextmenu event being dispatched, and |userEvent| be the user interaction event that caused the firing of |event|.
Event |userEvent| could be a non-PointerEvent; for example, it is aKeyboardEvent when aclick event dispatch is caused by hitting the spacebar on a checkbox element.
When |userEvent| is aPointerEvent, |userEvent| is a {{pointerup}} for aclick orauxclick event, and either a {{pointerdown}} or a {{pointerup}} event (depending on native platform convention) for acontextmenu event.
PointerEvent, dispatch |event| following the [[UIEVENTS]] spec without overriding |event| target and skip the remaining steps below.Define |target| as follows:
If |event| is acontextmenu event, or |userEvent| was dispatched while the corresponding pointer was captured, then let |target| be the target of |userEvent|.
Otherwise (|event| is aclick orauxclick event for which |userEvent| is apointerup event that was dispatched uncaptured) let |target| be the nearest common inclusive ancestor of the correspondingpointerdown andpointerup targets in the DOM at the moment |event| is being dispatched.
Dispatch |event| to |target| following the [[UIEVENTS]] spec.
The user's environment might be configured to associate vertical scrollingwith rotation along the y-axis, horizontal scrolling with rotation along thex-axis, and zooming with rotation along the z-axis.
The deltaX, deltaY, and deltaZ attributes of {{WheelEvent}} objects indicatea measurement along their respective axes in units of pixels, lines, orpages. The reported measurements are provided after an environment-specificalgorithm translates the actual rotation/movement of the wheel device intothe appropriate values and units.A user's environment settings can be customized to interpret actual rotation/movementof a wheel device in different ways.One movement of a commondented
mouse wheel can produce a measurement of 162 pixels(162 is just an example value, actual values can depend on the current screendimensions of the user-agent).But a user can change their default environment settings to speed-up their mouse wheel,increasing this number.Furthermore, some mouse wheel software can support acceleration (the faster the wheelis rotated/moved, the greater thedelta of each measurement) or even sub-pixelrotationmeasurements.Because of this, authors can not assume a givenrotation amount in one user agent willproduce the samedelta value in all user agents.
Individual user agents can (depending on their environment and hardware configuration)interpret the same physical user interaction on the wheel differently.For example, a vertical swipe on the edge of a trackpad from top to bottom can beinterpreted as a wheel action intended to either scroll thepage down or to pan the page up (i.e., resulting in either a positive or negativedeltaY value respectively).
Auser agent MUST create awheel event transaction when the first wheel eventis fired, so that all subsequent wheel events within a implementation-specific amount oftime can be targetted at the same element. Awheel event transaction is series ofwheel events that are associated with a single user gesture. Thewheel event transaction MUST have an associated event target that is thetopmost event target at the time the first wheel event occurs in the group.If a series of wheel events targetted in a scrollable element start above a child element,later events for the same user gesture may occur over the child element.
[Exposed=Window]interface WheelEvent : MouseEvent {constructor(DOMString type, optional WheelEventInit eventInitDict = {});// DeltaModeCodeconst unsigned long DOM_DELTA_PIXEL = 0x00;const unsigned long DOM_DELTA_LINE= 0x01;const unsigned long DOM_DELTA_PAGE= 0x02;readonly attribute double deltaX;readonly attribute double deltaY;readonly attribute double deltaZ;readonly attribute unsigned long deltaMode;};0.0.0.0.0.0.deltaMode attribute contains an indication ofthe units of measurement for thedelta values. Thedefault value is {{WheelEvent/DOM_DELTA_PIXEL}} (pixels).This attribute MUST be set to one of the DOM_DELTA constants toindicate the units of measurement for thedelta values.The precise measurement is specific to device, operating system,and application configurations.Theun-initialized value of this attribute MUST be0.dictionary WheelEventInit : MouseEventInit {double deltaX = 0.0;double deltaY = 0.0;double deltaZ = 0.0;unsigned long deltaMode = 0;};deltaZ attribute.deltaZ attribute.| Type | wheel |
|---|---|
| Interface | {{WheelEvent}} |
| Sync / Async | Async |
| Bubbles | Yes |
| Trusted Targets | Element |
| Cancelable | Varies |
| Composed | Yes |
| Default action | Scroll (or zoom) the document |
| Context (trusted events) |
|
In someuser agents, or with some input devices, the speedthat the wheel has been turned can affect thedelta values,with a faster speed producing a higherdelta value.
CallingpreventDefault on a wheel event can preventor otherwise interrupt scrolling. For maximum scroll performance, auser agent may not wait for each wheel event associated with the scrollto be processed to see if it will be canceled. In such cases the useragent should generatewheel events whosecancelable property isfalse, indicating thatpreventDefault cannot be used to prevent or interruptscrolling. Otherwisecancelable will betrue.
In particular, a user agent should generate only uncancelablewheel events when itobservesthat there are no non-passive listeners for the event.
The following section describes extensions to the existing {{Element}} interface to facilitate the setting and releasing of pointer capture.
partial interface Element { undefined setPointerCapture (long pointerId); undefined releasePointerCapture (long pointerId); boolean hasPointerCapture (long pointerId);};Set pointer capture for the pointer identified by the argument {{PointerEvent/pointerId}} to the element on which this method is invoked. For subsequent events of the pointer, the capturing target will substitute the normal hit testing result as if the pointer is always over the capturing target, and they MUST always be targeted at this element until capture is released. The pointer MUST be in itsactive buttons state for this method to be effective, otherwise it fails silently. When the provided method's argument does not match any of theactive pointers, [=exception/throw=] a {{"NotFoundError"}} {{DOMException}}.
Release pointer capture for the pointer identified by the argument {{PointerEvent/pointerId}} from the element on which this method is invoked. Subsequent events for the pointer follow normal hit testing mechanisms (out of scope for this specification) for determining the event target. When the provided method's argument does not match any of theactive pointers, [=exception/throw=] a {{"NotFoundError"}} {{DOMException}}.
Indicates whether the element on which this method is invoked haspointer capture for the pointer identified by the argument {{PointerEvent/pointerId}}. In particular, returnstrue if thepending pointer capture target override for {{PointerEvent/pointerId}} is set to the element on which this method is invoked, andfalse otherwise.
The following section describes extensions to the existing {{GlobalEventHandlers}} mixin to facilitate the event handler registration.
partial interface mixin GlobalEventHandlers { attribute EventHandler onpointerover; attribute EventHandler onpointerenter; attribute EventHandler onpointerdown; attribute EventHandler onpointermove; [SecureContext] attribute EventHandler onpointerrawupdate; attribute EventHandler onpointerup; attribute EventHandler onpointercancel; attribute EventHandler onpointerout; attribute EventHandler onpointerleave; attribute EventHandler ongotpointercapture; attribute EventHandler onlostpointercapture;};The {{Navigator}} interface is defined in [[HTML]]. This specification extends theNavigator interface to provide device detection support.
partial interface Navigator { readonly attribute long maxTouchPoints;};The getter steps are:
Return the maximum number of simultaneous touch contacts supported by the device. In the case of devices with multiple digitizers (e.g. multiple touchscreens), the value MUST be the maximum of the set of maximum supported contacts by each individual digitizer.
For example, suppose a device has 3 touchscreens, which support 2, 5, and 10 simultaneous touch contacts, respectively. The value ofmaxTouchPoints should be10.
maxTouchPoints value of greater than0 indicates the user's device is capable of supporting touch input, it does not necessarily mean the userwill use touch input. Authors should be careful to also consider other input modalities that could be present on the system, such as mouse, pen, or screen readers.maxTouchPoints is often used to ensure that the interaction model of the content can be recognized by the current hardware. UI affordances can be provided to users with less capable hardware. On platforms where the precise number of touch points is not known, the minimum number guaranteed to be recognized is provided. Therefore, it is possible for the number of recognized touch points to exceed the value ofmaxTouchPoints.As noted inAttributes and Default Actions, viewport manipulations (panning and zooming) cannot be suppressed by canceling a pointer event. Instead, authors must declaratively define which of these behaviors they want to allow, and which they want to suppress, using thetouch-action CSS property.
touch-action CSS property defined in this specification appears to refer only to touch inputs, it does in fact apply to all forms of pointer inputs that allowdirect manipulation for panning and zooming.touch-action CSS property| Name: | touch-action |
|---|---|
| Value: | auto |none | [ [pan-x |pan-left |pan-right ] || [pan-y |pan-up |pan-down ] ] |manipulation |
| Initial: | auto |
| Applies to: | all elements except: non-replaced inline elements, table rows, row groups, table columns, and column groups |
| Inherited: | no |
| Percentages: | N/A |
| Media: | visual |
| Computed value: | same as specified value |
| Canonical order: | per grammar |
| Animation type: | not animatable |
Thetouch-action CSS property determines whetherdirect manipulation interactions (which are not limited to touch, despite the property's name) MAY trigger the user agent's panning and zooming behavior. See the section ontouch-action values.
Right before starting to pan or zoom, theuser agent MUSTsuppress a pointer event stream if all of the following conditions are true:
touch-action does not apply/cascade through to embedded browsing contexts. For instance, even applyingtouch-action to an<iframe> won't have any effect on the behavior of direct manipulation interactions for panning and zooming within the<iframe> itself.When a user interacts with an element using adirect manipulation pointer (such as touch or stylus on a touchscreen), the effect of that input is determined by the value of thetouch-action property, and the default direct manipulation behaviors of the element and its ancestors, as follows:
touch-action if the behavior is allowed in the coordinate space of the element. Note that if CSS transforms have been applied, the element's coordinate space may differ from the screen coordinate in a way that affects the conformity here; for example, the X axis of an element rotated by 90 degrees with respect to the screen will be parallel to the Y-axis of the screen coordinate.touch-action property of each element between the hit tested element and its nearest inclusive ancestor that is a [=scroll container=] (as defined in [[CSS-OVERFLOW-3]]).touch-action property of each element between the hit tested element and thedocument element of the [=top-level browsing context=] (as defined in [[HTML]]).touch-action value will be ignored for the duration of the action. For instance, programmatically changing thetouch-action value for an element fromauto tonone as part of a {{pointerdown}} handler script will not result in the user agent aborting or suppressing any of the pan or zoom behavior for that input for as long as that pointer is active.touch-action values ofpan-*, once the user agent has determined whether to handle a gesture directly or not at the start of the gesture, a subsequent change in the direction of the same gesture SHOULD be ignored by the user agent for as long as that pointer is active. For instance, if an element has been set totouch-action: pan-y (meaning that only vertical panning is handled by the user agent), and a touch gesture starts off horizontally, no vertical panning should occur if the user changes the direction of their gesture to be vertical while their finger is still touching the screen.touch-action values of multiple concurrent pointers is out of scope for this specification.touch-action valuesThetouch-action property covers direct manipulation behaviors related to viewport panning and zooming. Any additional user agent behaviors, such as text selection/highlighting, or activating links and form controls, MUST NOT be affected by this CSS property.
auto ornone values, are out of scope for this specification.pan-x orpan-y), the axis cannot be changed during panning.touch-action values common in implementations are defined in [[COMPAT]].touch-action property only applies to elements that support both the CSSwidth andheight properties (see [[CSS21]]). This restriction is designed to facilitate user agent optimizations forlow-latencydirect manipulation panning and zooming. For elements not supported by default, such as<span> which is anon-replaced inline element, authors can set thedisplay CSS property to a value, such asblock, that supportswidth andheight. Future specifications could extend this API to all elements.The direction-specific pan values are useful for customizing some overscroll behaviors. For example, to implement a simple pull-to-refresh effect the document'stouch-action can be set topan-x pan-down whenever the scroll position is0 andpan-x pan-y otherwise. This allows pointer event handlers to define the behavior for upward panning/scrolling that start from the top of the document.
The direction-specific pan values can also be used for composing a component that implements custom panning with pointer event handling within an element that scrolls natively (or vice-versa). For example, an image carousel may usepan-y to ensure it receives pointer events for any horizontal pan operations without interfering with vertical panning of the document. When the carousel reaches its right-most extent, it may change itstouch-action topan-y pan-right so that a subsequent scroll operation beyond its extent can scroll the document within the viewport if possible. It's not possible to change the behavior of a panning/scrolling operation while it is taking place.
auto user agents typically add 300ms of delay beforeclick to allow for double-tap gestures to be handled. In these cases, explicitly settingtouch-action: none ortouch-action: manipulation will remove this delay. Note that the methods for determining a tap or double-tap gesture are out of scope for this specification.<div style="touch-action: none;"> This element receives pointer events for all direct manipulation interactions that otherwise lead to panning or zooming.</div><div style="touch-action: pan-x;"> This element receives pointer events when not panning in the horizontal direction.</div><div style="overflow: auto;"> <div style="touch-action: none;"> This element receives pointer events for all direct manipulation interactions that otherwise lead to panning or zooming. </div> <div> Direct manipulation interactions on this element MAY be consumed for manipulating the parent. </div></div><div style="overflow: auto;"> <div style="touch-action: pan-y;"> <div style="touch-action: pan-x;"> This element receives pointer events for all direct manipulation interactions because it allows only horizontal panning yet an intermediate ancestor (between it and the scrollable element) only allows vertical panning. Therefore, no direct manipulation behaviors for panning/zooming are handled by the user agent. </div> </div></div><div style="overflow: auto;"> <div style="touch-action: pan-y pan-left;"> <div style="touch-action: pan-x;"> This element receives pointer events when not panning to the left. </div> </div></div>Pointer capture allows the events for a particular pointer (including anycompatibility mouse events) to be retargeted to a particular element other than the normalhit test result of the pointer's location. This is useful in scenarios like a custom slider control (e.g. similar to the [[HTML]]<input type="range"> control). Pointer capture can be set on the slider thumb element, allowing the user to slide the control back and forth even if the pointer slides off of the thumb.

Pointer capture is set on an |element| of type {{Element}} by calling theelement.setPointerCapture(pointerId) method. When this method is invoked, theuser agent MUST run the following steps:
Pointer capture is released on an element explicitly by calling theelement.releasePointerCapture(pointerId) method. When this method is called, theuser agent MUST run the following steps:
Inputs that implementdirect manipulation interactions for panning and zooming (such as touch or stylus on a touchscreen) SHOULD behave exactly as if {{Element/setPointerCapture}} was called on the target element just before the invocation of any {{pointerdown}} listeners. The {{Element/hasPointerCapture}} API may be used (for instance, in a {{pointerdown}} listener) to determine whether this has occurred. If {{Element/releasePointerCapture}} is not called for the pointer before the next pointer event is fired, then a {{gotpointercapture}} event will be dispatched to the target (as normal) indicating that capture is active.
Immediately after firing the {{pointerup}} or {{pointercancel}} events, theuser agent MUST clear thepending pointer capture target override for the {{PointerEvent/pointerId}} of the {{pointerup}} or {{pointercancel}} event that was just dispatched, and then runprocess pending pointer capture steps to fire {{lostpointercapture}} if necessary. After runningprocess pending pointer capture steps, if the pointer supports hover,user agent MUST also send corresponding boundary events necessary to reflect the current position of the pointer with no capture.
When thepointer capture target override is no longer [=connected=] [[DOM]], thepointer capture target override SHOULD be set to the document.
When thepending pointer capture target override is no longer [=connected=] [[DOM]], thepending pointer capture target override node SHOULD be cleared.
When a pointer lock [[PointerLock]] is successfully applied on an element, theuser agent MUST run the steps as if the {{Element/releasePointerCapture}} method has been called if any element is set to be captured or pending to be captured.
For performance reasons, user agents may choose not to send a {{pointermove}} event every time ameasurable property (such as coordinates, pressure, tangential pressure, tilt, twist, or contact geometry) of a pointer is updated. Instead, they may coalesce (combine/merge) multiple changes into a single {{pointermove}} or {{pointerrawupdate}} event. While this approach helps in reducing the amount of event handling theuser agent MUST perform, it will naturally reduce the granularity and fidelity when tracking a pointer position, particularly for fast and large movements. Using the {{PointerEvent/getCoalescedEvents}} method it is possible for applications to access the raw, un-coalesced position changes. These allow for a more precise handling of pointer movement data. In the case of drawing applications, for instance, the un-coalesced events can be used to draw smoother curves that more closely match the actual movement of a pointer.

getCoalescedEvents() (the red circles) results in a smoother approximation of the pointer movement.APointerEvent has an associatedcoalesced events list (a list of zero or morePointerEvents). For trusted {{pointermove}} and {{pointerrawupdate}} events, the list is a sequence of allPointerEvents that were coalesced into this event. The "parent" trusted {{pointermove}} and {{pointerrawupdate}} event represents an accumulation of these coalesced events, but may have additional processing (for example to align with the display refresh rate). As a result, the coalesced events lists for these events always contain at least one event. For all other trusted event types, it is an empty list. Untrusted events have theircoalesced events list initialized to the value passed to the constructor.
false but the same bits in thecoalesced events list remain unchanged from their originaltrue values.The events in the coalesced events list of a trusted event will have:
pointerType, andisPrimary as the dispatched "parent" pointer event.<style> /* Disable intrinsic user agent direct manipulation behaviors (such as panning or zooming) so that all events on the canvas element are given to the application instead. */ canvas { touch-action: none; }</style><canvas width="500px" height="500px"></canvas><script> const canvas = document.getElementById("drawSurface"), context = canvas.getContext("2d"); canvas.addEventListener("pointermove", (e)=> { if (e.getCoalescedEvents) { for (let coalesced_event of e.getCoalescedEvents()) { paint(coalesced_event); // Paint all raw/non-coalesced points } } else { paint(e); // Paint the final coalesced point } }); function paint(event) { if (event.buttons>0) { context.fillRect(event.clientX, event.clientY, 5, 5); } }</script>The order of all these dispatched events MUST match the actual order of the original events. For example if a {{pointerdown}} event causes the dispatch for the coalesced {{pointermove}} events theuser agent MUST first dispatch one {{pointermove}} event with all those coalesced events of a {{PointerEvent/pointerId}} followed by the {{pointerdown}} event.
Here is an example of the actual events happening with increasing {{Event/timeStamp}} values and the events dispatched by the user agent:
| Actual events | Dispatched events |
|---|---|
| pointer ({{PointerEvent/pointerId}}=2) coordinate change | {{pointerrawupdate}} ({{PointerEvent/pointerId}}=2) w/ one coalesced event |
| pointer ({{PointerEvent/pointerId}}=1) coordinate change | {{pointerrawupdate}} ({{PointerEvent/pointerId}}=1) w/ one coalesced event |
| pointer ({{PointerEvent/pointerId}}=2) coordinate change | {{pointerrawupdate}} ({{PointerEvent/pointerId}}=2) w/ one coalesced event |
| pointer ({{PointerEvent/pointerId}}=2) coordinate change | {{pointerrawupdate}} ({{PointerEvent/pointerId}}=2) w/ one coalesced event |
| pointer ({{PointerEvent/pointerId}}=1) coordinate change | {{pointerrawupdate}} ({{PointerEvent/pointerId}}=1) w/ one coalesced event |
| pointer ({{PointerEvent/pointerId}}=2) coordinate change | {{pointerrawupdate}} ({{PointerEvent/pointerId}}=2) w/ one coalesced event |
| pointer ({{PointerEvent/pointerId}}=1) button press | {{pointermove}} ({{PointerEvent/pointerId}}=1) w/ two coalesced events {{pointermove}} ({{PointerEvent/pointerId}}=2) w/ four coalesced events {{pointerdown}} ({{PointerEvent/pointerId}}=1) w/ zero coalesced events |
| pointer ({{PointerEvent/pointerId}}=2) coordinate change | {{pointerrawupdate}} ({{PointerEvent/pointerId}}=2) w/ one coalesced event |
| pointer ({{PointerEvent/pointerId}}=2) coordinate change | {{pointerrawupdate}} ({{PointerEvent/pointerId}}=2) w/ one coalesced event |
| pointer ({{PointerEvent/pointerId}}=1) button release | {{pointermove}} ({{PointerEvent/pointerId}}=2) w/ two coalesced events {{pointerup}} ({{PointerEvent/pointerId}}=1) w/ zero coalesced events |
Some user agents have built-in algorithms which, after a series of confirmed pointer movements, can make a prediction (based on the preceding events for the current gesture, and the speed/trajectory of the movement) what the position of future pointer movements may be. Applications can use this information with the {{PointerEvent/getPredictedEvents}} method to speculatively "draw ahead" to a predicted position to reduce perceived latency, and then discarding these predicted points once the actual points are received.

APointerEvent has an associatedpredicted events list (a list of zero or morePointerEvents). For trusted {{pointermove}} events, it is a sequence ofPointerEvents that the user agent predicts will follow the event in the future. For all other trusted event types, it is an empty list. Untrusted events have theirpredicted events list initialized to the value passed to the constructor.
Whilepointerrawupdate events may have a non-emptycoalesced events list, theirpredicted events list will, for performance reasons, usually be an empty list.
false but the same bits in thepredicted events list remain unchanged from their originaltrue values.The number of events in the list and how far they are from the current timestamp are determined by the user agent and the prediction algorithm it uses.
The events in the predicted events list of a trusted event will have:
pointerType, andisPrimary as the dispatched "parent" pointer event.Note that authors should only consider predicted events as valid predictions until the next pointer event is dispatched. It is possible, depending on how far into the future the user agent predicts events, that regular pointer events are dispatched earlier than the timestamp of one or more of the predicted events.
let predicted_points = [];window.addEventListener("pointermove", function(event) { // Clear the previously drawn predicted points. for (let e of predicted_points.reverse()) { clearPoint(e.pageX, e.pageY); } // Draw the actual movements that happened since the last received event. for (let e of event.getCoalescedEvents()) { drawPoint(e.pageX, e.pageY); } // Draw the current predicted points to reduce the perception of latency. predicted_points = event.getPredictedEvents(); for (let e of predicted_points) { drawPoint(e.pageX, e.pageY); }});When a trustedPointerEvent is created, user agents SHOULD run the following steps for each event in thecoalesced events list andpredicted events list:
pointerType,isPrimary and {{Event/isTrusted}} to match the respective properties of the "parent" pointer event.When a trustedPointerEvent's {{Event/target}} is changed, user agents SHOULD, for each event in thecoalesced events list andpredicted events list:
The vast majority of web content existing today codes only to Mouse Events. The following describes an algorithm for how theuser agent MAY map generic pointer input to mouse events for compatibility with this content.
The compatibility mapping with mouse events is an OPTIONAL feature of this specification. User agents are encouraged to support the feature for best compatibility with existing legacy content.
At a high level, compatibility mouse events are intended to be "interleaved" with their respective pointer events. However, this specific order is not mandatory, and user agents that implement compatibility mouse events MAY decide to delay or group the dispatch of mouse events, as long as their relative order is consistent.
Particularly in the case of touchscreen inputs, user agents MAY apply additional heuristics for gesture recognition (unless explicitly suppressed by authors throughtouch-action). During a sequence of events between a {{pointerdown}} event and a {{pointerup}} event, the gesture recognition may have to wait until the {{pointerup}} event to detect or ignore a gesture. As a result the compatibility mouse events for the whole sequence may be dispatched together after the last {{pointerup}} event, if the user agent determined that an interaction was not intended as a particular gesture. These specifics of user agent gesture recognition are not defined in this specification, and they may differ between implementations.
Regardless of their support for compatibility mouse events, the user agents MUST always support theclick,auxclick andcontextmenu events because these events are of typePointerEvent and are therefore notcompatibility mouse events. CallingpreventDefault during a pointer event MUST NOT have an effect on whetherclick,auxclick, orcontextmenu are fired or not.
The relative order of some of these high-level events (such ascontextmenu, [=HTMLElement/focus=], [=HTMLElement/blur=]) with pointer events is undefined and varies between user agents. For example, in some user agentscontextmenu will often follow a {{pointerup}}, while in others it'll often precede a {{pointerup}} or {{pointercancel}}, and in some situations it may be fired without any corresponding pointer event (for instance, as a result of a keyboard interaction).
In addition, user agents may apply their own heuristics to determine whether or not aclick,auxclick, orcontextmenu event should be fired. Some user agents may choose not to fire these events if there are other (non-primary) pointers of the same type, or other primary pointers of a different type. User agents may determine that a particular action was not a "clean" tap, click, or long-press (for instance, if an interaction with a finger on a touch screen includes too much movement while the finger is in contact with the screen) and decide not to fire aclick,auxclick, orcontextmenu event. These aspects of user agent behavior are not defined in this specification, and they may differ between implementations.
Unless otherwise noted, the target of any mapped mouse event SHOULD be the same target as the respective pointer event unless the target is no longer participating in itsownerDocument's tree. In this case, the mouse event should be fired at the original target's nearest ancestor node (at the time it was removed from the tree) that still participates in itsownerDocument's tree, meaning that a new event path (based on the new target node) is built for the mouse event.
Authors can prevent the production of certain compatibility mouse events by canceling the {{pointerdown}} event.
Mouse events can only be prevented when the pointer is down. Hovering pointers (e.g. a mouse with no buttons pressed) cannot have their mouse events prevented.
Themouseover,mouseout,mouseenter, andmouseleave events are never prevented (even if the pointer is down).
Compatibility mouse events can't be prevented when a pointer event {{EventListener}} is set to be {{AddEventListenerOptions/passive}} [[DOM]].
While onlyprimary pointers can produce compatibility mouse events,multiple primary pointers can be active simultaneously, each producing its own compatibility mouse events. For compatibility with scripts relying on MouseEvents, the mouse transition events (mouseover,mouseout,mouseenter andmouseleave) SHOULD simulate the movement of asingle legacy mouse input. This means that the entry/exit state for every event target is valid, in accordance with [[UIEVENTS]]. User agents SHOULD guarantee this by maintaining theeffective position of the legacy mouse pointer in the document as follows.
Right before firing a {{pointerdown}}, {{pointerup}} or {{pointermove}} event, or a {{pointerleave}} event at thewindow, the user agent SHOULD run the following steps:
mouseover,mouseout,mouseenter andmouseleave events as per [[UIEVENTS]] for a mouse moving from the currenteffective legacy mouse pointer position to |T|. Consider an unset value of either currenteffective legacy mouse pointer position or |T| as an out-of-window mouse position.Theeffective position of the legacy mouse pointer models the fact that we cannot always have a direct mapping from pointer transition events (pointerover,pointerout,pointerenter andpointerleave) to corresponding legacy mouse transition events (mouseover,mouseout,mouseenter andmouseleave). The following animation illustrates a case where a user agent needs to dispatch more legacy mouse transition events than pointer transition events to be able to reconcile two primary pointers using a single legacy mouse input.
In this animation, note the time period between the mouse click and the touch tap. Button 1 receives nopointerout event (because the "real" mouse pointer didn't leave the button rectangle within this period), but Button 1 receives amouseout event when theeffective position of the legacy mouse pointer moves to Button 2 on touch tap. Similarly, in the time period between the touch tap and the moment before the mouse leaves Button 1, Button 1 receives nopointerover event for the same reason, but Button 1 receives amouseover event when theeffective position of the legacy mouse pointer moves back inside Button 1.
Whenever the user agent is to dispatch a pointer event for a device that supports hover, it SHOULD run the following steps:
isPrimary property for the pointer event to be dispatched isfalse then dispatch the pointer event and terminate these steps.window, dispatch compatibility mouse transition events as described inTracking the effective position of the legacy mouse pointer.PREVENT MOUSE EVENT flag for thispointerType.PREVENT MOUSE EVENT flag isnot set for thispointerType and the pointer event dispatched was:mousedown event.mousemove event.mouseup event.mouseup event at thewindow.PREVENT MOUSE EVENT flag for thispointerType.Some devices, such as most touchscreens, do not support hovering a coordinate (or set of coordinates) while not in the active state. Much existing content coded to mouse events assumes that a mouse is producing the events and thus certain qualities are generally true:
mousemove event on an element before clicking it.This requires that user agents provide a different mapping for these types of input devices. Whenever the user agent is to dispatch a pointer event for a device thatdoes not support hover, it SHOULD run the following steps:
isPrimary property for the pointer event to be dispatched isfalse then dispatch the pointer event and terminate these steps.mousemove event (for compatibility with legacy mouse-specific code).window, dispatch compatibility mouse transition events as described inTracking the effective position of the legacy mouse pointer.PREVENT MOUSE EVENT flag for thispointerType.PREVENT MOUSE EVENT flag isnot set for thispointerType and the pointer event dispatched was:mousedown event.mousemove event.mouseup event.mouseup event at thewindow.PREVENT MOUSE EVENT flag for thispointerType.If the user agent supports both Touch Events (as defined in [[TOUCH-EVENTS]]) and Pointer Events, theuser agent MUST NOT generateboth the compatibility mouse events as described in this section, and thefallback mouse events outlined in [[TOUCH-EVENTS]].
The activation of an element (click) with a primary pointer thatdoes not support hover (e.g. single finger on a touchscreen) would typically produce the following event sequence:
mousemovepointerentermouseovermouseentermousedownmousemove events, depending on movement of the pointermouseupmouseoutmouseleaveclickIf, however, the {{pointerdown}} event [=Event/canceled flag=] is set during this interaction then the sequence of events would be:
mousemovepointerentermouseovermouseentermouseoutmouseleaveclickThis appendix discusses security and privacy considerations for Pointer Events implementations. The discussion is limited to security and privacy issues that arise directly from implementation of the event model, APIs and events defined in this specification.
Many of the event types defined in this specification are dispatched in response to user actions. This allows malicious event listeners to gain access to information users would typically consider confidential, e.g., the exact path/movement of a user's mouse/stylus/finger while interacting with a page.
Pointer events contain additional information (where supported by the user's device), such as the angle or tilt at which a pen input is held, the geometry of the contact surface, and the pressure exerted on the stylus or touch screen. Information about angle, tilt, geometry and pressure are directly related to sensors on the user's device, meaning that this specification allows an origin access to these sensors.
This sensor data, as well as the ability to determine the type of input mechanism (mouse, touch, pen) used, may be used to infer characteristics of a user, or of the user's device and environment. These inferred characteristics and any device/environment information may themselves be sensitive — for instance, they may allow a malicious site to further infer if a user is using assistive technologies. This information can also be potentially used for the purposes of building a user profile and/or attempting to "fingerprint" and track a particular user.
As mitigation, user agents may consider including the ability for users to disable access to particular sensor data (such as angle, tilt, pressure), and/or to make it available only after an explicit opt-in from the user.
This specification defines the method by which authors can access "predicted events". The specification does not, itself, define the algorithms that user agents should use for their prediction. The specification authors envisage the algorithms to only rely on preceding pointer events related to the current gesture that a user is performing. It is the responsibility of user agents to ensure that their specific implementation of a prediction algorithm does not rely on any additional data - such as the user's full interaction history across different sites - that could reveal sensitive information about a user or be used to "fingerprint" and track them.
Beyond these considerations, the working group believes that this specification:
buttons property. For mouse, this is when the device has at least one button depressed. For touch, this is when there is physical contact with the digitizer. For pen, this is when either the pen has physical contact with the digitizer, or at least one button is depressed while hovering.Measurable properties represent values relating to continuous pointer sensor data that is expressed using a real number or an integer from a large domain. For pointer events,width,height,pressure,tangentialPressure,tiltX,tiltY,twist,altitudeAngle,azimuthAngle, and the [[UIEVENTS]] Mouse Event model propertiesscreenX,screenY,clientX,clientY are measurable properties.
In contrast {{PointerEvent/pointerId}},pointerType,isPrimary, and the [[UIEVENTS]] Mouse Event model propertiesbutton,buttons,ctrlKey,shiftKey,altKey, andmetaKey are not considered measurable properties, as they don't relate to sensor data.
hit testingfacility is used to determine the target. For specific details regarding hit testing and stacking order, refer to thehost language.
This section is normative.The following features are obsolete and should only be implemented byuser agents that require compatibility with legacy software. See also thelegacy event initializers in [[UIEvents]].
partial interface MouseEvent {// Deprecated in this specificationundefined initMouseEvent(DOMString typeArg,optional boolean bubblesArg = false,optional boolean cancelableArg = false,optional Window? viewArg = null,optional long detailArg = 0,optional long screenXArg = 0,optional long screenYArg = 0,optional long clientXArg = 0,optional long clientYArg = 0,optional boolean ctrlKeyArg = false,optional boolean altKeyArg = false,optional boolean shiftKeyArg = false,optional boolean metaKeyArg = false,optional short buttonArg = 0,optional EventTarget? relatedTargetArg = null);};UIEvent.initUIEvent().TheinitMouseEvent method is deprecated, butsupported for backwards-compatibility with widely-deployedimplementations.
null.null.Many thanks to lots of people for their proposals and recommendations, some of which are incorporated into this document. The group's Chair acknowledges contributions from the following past and present group members and participants: Mustaq Ahmed, Arthur Barstow, Ben Boyle, Matt Brubeck, Rick Byers, Marcos Cáceres, Cathy Chan, Bo Cupp, Domenic Denicola, Ted Dinklocker, Adam Ettenberger, Robert Flack, Dave Fleck, Mike Fraser, Ella Ge, Olga Gerchikov, Scott González, Kartikaya Gupta, Dominique Hazael-Massieux, Philippe Le Hégaret, Hayato Ito, Patrick Kettner, Patrick H. Lauke, Scott Low, Sangwhan Moon, Masayuki Nakano, Olli Pettay, Addison Phillips, Alan Pyne, Antoine Quint, Jacob Rossi, Kagami Sascha Rosylight, Doug Schepers, Ming-Chou Shih, Brenton Simpson, Dave Tapuska, Liviu Tinta, Asir Vedamuthu, Lan Wei, Jeffrey Yasskin, Navid Zolghadr.
Thanks to those who took care of mouse and wheel events in the past: Gary Kacmarcik, Travis Leithead, and thevarious contributors over the years.
Special thanks to those that helped pioneer the first edition of this model, including especially: Charu Chandiram, Peter Freiling, Nathan Furtwangler, Thomas Olsen, Matt Rakow, Ramu Ramanathan, Justin Rogers, Jacob Rossi, Reed Townsend and Steve Wright.
The following is an informative summary of substantial and major editorial changes between publications of this specification, relative to the [[PointerEvents3]] specification. See thecomplete revision history of the Editor's Drafts of this specification.