v148 · Web APIs · Drag & Drop
Pointer event suppression on drag start
Chrome 148 aligns with the HTML spec: when a drag operation starts, the browser sends a pointercancel event to the drag source to signal that the pointer event stream has ended. This ensures that pointer event listeners don't continue to fire unexpectedly during a drag.
concepts
-
Drag Events Demo
Drag the element and watch the event log. In Chrome 148+, a
pointercancelevent fires as soon as the drag starts, suppressing furtherpointermoveevents on the drag source. Before Chrome 148, pointer move events continued firing during the drag. -
Event Sequence Viewer
Shows the full expected event sequence for a drag gesture:
pointerdown→pointermove→ drag start →pointercancel→ drag events →pointerup. Compare Chrome 148 vs prior behaviour. -
State Machine Visualiser
Canvas-drawn state machine showing Idle → Pointer → Drag → Done transitions in real time. Drag the target element and watch the
pointercancelnode light up — the Chrome 148 spec fix made visible. -
Multi-touch Drag Demo
A 3×3 grid of draggable tiles with a live event log timestamped by pointer ID. Start dragging one tile and watch
pointercancelsuppress that pointer's stream. A "Simulate second touch" button starts a second independent pointer — demonstrating that only the dragging pointer is suppressed, others remain active. State diagram and per-pointer-ID badges show suppressed vs active status at a glance. -
Cleanup Pattern Demo
Side-by-side comparison of a broken pointer-tracking pattern (no
pointercancelhandler — move events leak into the drag) vs the correct pattern (cleans up viapointercancelthe moment Chrome 148 fires it at drag start). A progress bar and event log make the difference visible as you drag each card.
why it shipped
The HTML specification says that when a drag starts, the user agent should fire pointercancel on the drag source to indicate the pointer event stream has been "captured" by the drag. Before Chrome 148, Chrome didn't do this — pointer event listeners could fire unexpectedly during a drag, causing issues for custom drag-and-drop implementations that tried to handle both the Drag and Drop API and Pointer Events simultaneously.
the event sequence
// Chrome 148+ event sequence for a drag gesture:
// 1. pointerdown → drag starts here (mousedown equivalent)
// 2. pointermove → brief move before drag threshold met
// 3. pointercancel → ← NEW in Chrome 148: drag took over the pointer stream
// 4. dragstart → HTML Drag and Drop API takes over
// 5. drag → fires while dragging (pointer events suppressed)
// 6. dragenter / dragover / dragleave on targets
// 7. drop → on valid drop target
// 8. dragend → drag sequence complete
// Before Chrome 148:
// pointerdown → pointermove → pointermove → ... (kept firing during drag!)
// → dragstart (but pointer events weren't cancelled)
el.addEventListener('pointercancel', e => {
// Chrome 148+: fires when drag starts
// Safe to clean up any pointer-tracking state here
cleanup();
});
references
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗