DEV Community

WDSEGA
WDSEGA

Posted on

Component Deep Dive #24: Drag and Sort - Build a Draggable List Without Any Library

Web Component Dictionary v2.0 - 83 Components, Bilingual, Live Preview
Live Demo | Buy on Payhip

Sortable.js? 35KB. react-beautiful-dnd? 35KB+. Today we build drag-sort from zero: 0 dependencies, 20 lines of core logic.

Why Not HTML5 Drag and Drop API

3 pitfalls:

  1. Must preventDefault() on dragover - otherwise drop won't fire
  2. Mobile doesn't support it - iOS/Android completely ignore HTML5 DnD
  3. Drag ghost can't be customized with HTML

Pointer Events Solution (Cross-Platform)

Works for mouse + touch:

javascript
let dragItem, dragIdx, startY;
list.addEventListener('pointerdown', e => {
dragItem = e.target.closest('.drag-item');
dragIdx = [...list.children].indexOf(dragItem);
startY = e.clientY;
dragItem.classList.add('dragging');
dragItem.setPointerCapture(e.pointerId);
});

Center-point threshold: when drag item center crosses target center ? insertBefore swap.

After each swap: reset startY + transform - otherwise displacement stacks.

CSS Requirements

touch-action: none - critical! Without it, mobile scrolls instead of dragging.
user-select: none - prevents text selection during drag.

5 Common Bugs

  1. Missing touch-action: none - scroll vs drag conflict on mobile
  2. Missing user-select: none - text selected during drag
  3. Not resetting startY after swap - transform accumulates, element flies away
  4. Missing setPointerCapture - pointer stolen by other elements
  5. transition conflicting with drag transform - disable during drag

When to Use Library vs Self-Implement

Simple list sort ? self ? | Multi-column cross-container ? library ? | Grid ? library ?

80% of drag-sort needs are simple lists. 20 lines of logic is enough. No 35KB library needed.


Bilingual version at wdsega.github.io

Top comments (0)