v148 · pointer events · drag api · shipped · interop
Pointer event suppression on drag start
Chrome 148 now fires pointercancel, pointerout, and pointerleave events to the drag source element when a drag begins, matching the HTML specification and aligning with Firefox and Safari. Ships in Chrome 148 on all platforms.
at a glance
| Shipped in | Chrome 148 (desktop, Android, WebView) |
|---|---|
| Status | Enabled by default |
| Finch flag | SuppressPointerStreamAfterDrag |
| Spec | HTML — Drag and drop processing model |
| ChromeStatus | 6732314958757888 — Pointer event suppression on drag start |
what changed
When the user initiates a drag on an element, the browser begins managing pointer input at the OS level to handle the drag gesture. The HTML specification says the browser must indicate to the drag source that the pointer event stream has ended — i.e., fire the events that tell the element "you are no longer receiving pointer events."
Before Chrome 148, this was only partially done: touch drags on Android fired these events, but mouse-based drags on desktop did not. Chrome 148 completes the implementation: whenever a drag starts, the drag source now receives:
pointercancel— the pointer has been cancelled and no more events will followpointerout— the pointer has left the element's hit-testing areapointerleave— the pointer has left the element (bubbles up the ancestor chain)
why it matters
Code that listens for pointercancel to clean up state (e.g., remove a CSS class applied on pointerdown, cancel an in-progress gesture, or release a pointer capture) now works correctly on desktop during drag operations. Previously, desktop drag sources would not receive pointercancel, so cleanup code that relied on it was never triggered for mouse drags.
element.addEventListener('pointerdown', (e) => {
element.classList.add('dragging');
element.setPointerCapture(e.pointerId);
});
// Before Chrome 148: this never fired on desktop mouse drag start
// Chrome 148+: fires correctly when a drag begins
element.addEventListener('pointercancel', () => {
element.classList.remove('dragging');
});
event order on drag start
When the browser decides a drag has begun, the event sequence at the drag source is:
| Order | Event | Notes |
|---|---|---|
| 1 | dragstart | Fired on the drag source; drag is now active |
| 2 | pointercancel | New in Chrome 148 for desktop; was already fired for touch on Android |
| 3 | pointerout | New in Chrome 148 for desktop |
| 4 | pointerleave | New in Chrome 148 for desktop; bubbles up ancestors |
After these events fire, no further pointer events are dispatched to the drag source for that pointer until a new pointerdown occurs.
browser support
| Chrome / Edge | 148 (desktop, Android, WebView) |
|---|---|
| Firefox | Shipped |
| Safari | Shipped |