JavaScript Logo

Vanilla JS drag handles for drag-and-drop

Imagine you have a form inside a draggable element in your application. We could simply set the draggable="true" attribute on the outer most element and then and it is draggable.

But making a DOM element draggable like this also means that all child elements act as a “source” of dragging. For some mouse gestures, such as highlighting text, this is problematic because the gesture is mistaken for dragging the parent element.

An animation of dragging when attempting to highlight text with the cursor

A better UX option is a “drag handle”: A specific child element that provides a cue for the dragging interaction, and that mediates when dragging of the parent element happens.

What I did was only set draggable="true" on outerDraggable when the grab handle gets a mousedown event.

dragHandle.addEventListener("mousedown", ()=>{
    outerDraggable.setAttribute("draggable", "true");
});

Then in the drop and dragend event handlers, I removed the draggable attribute from outerDraggable so that it “settles” and doesn’t misinterpret post-drag, drag-like mouse gestures unless the drag handle is “activated” with a mouse down.

Ensuring this happens on mousedown has the neat effect that you naturally drag the element “by” the handle. In reality, you could “click” the handle … then drag from anywhere in the element. This is actually a behaviour we want to keep, because not everyone is dragging with a mouse.

Simple but effective.