Frontend Essentials: Drag-and-Drop Sorting
Intro: ✍️ It's been a while. Quick post today on a frontend essential — drag-and-drop sorting. it's very important!
1. Overview
Frontend evolves fast. New tech keeps shipping, you can't keep up, you really can't (sob)~~~~. History marches on, and the frontend "Moore's Law" is that every 18 months, the bar for becoming a frontend engineer doubles.
haha, no pressure, back to the topic. The inspiration came from some recent work — drag interactions show up everywhere. Take the Transition Group demo on the Vue.js site:

So how do we build that? Let's take a look.
2. Drag-and-drop sorting
Drag
Step 1: To make something draggable, use the HTML
draggableattribute and set it totrue. That alone gives you the drag effect.
<div class="list">
<div draggable="true" class="list-item">1</div>
<div draggable="true" class="list-item">2</div>
<div draggable="true" class="list-item">3</div>
<div draggable="true" class="list-item">4</div>
<div draggable="true" class="list-item">5</div>
</div>Step 2: Add some CSS. Set up a
.movingstyle that we'll add dynamically with JS.
.list-item.moving {
background: transparent;
color: transparent;
border: 1px dashed #ccc;
}Sorting
The basic setup is done. Two more things to handle:
insert upinsert down
Step 1: When the drag starts, add the
.movingclass.
const list = document.querySelector('.list')
// track the element currently being dragged
let sourceNode = ''
list.ondragstart = (e) => {
setTimeout(() => {
e.target.classList.add('moving')
}, 0)
sourceNode = e.target
}Step 2: When the dragged element enters a target element, figure out the insert position.
list.ondragenter = (e) => {
// exclude two cases: the element itself, and the parent
if (e.target === list || e.target === sourceNode) {
return
}
// turn children into an array
const children = [...list.children]
// find target index and source index
const sourceIndex = children.indexOf(sourceNode)
const targetIndex = children.indexOf(e.target)
// if source is before target
if (sourceIndex < targetIndex) {
console.log('down')
// todo
} else {
console.log('up')
// todo
}
}Step 3: When the drag ends, remove the
.movingclass.
list.ondragend = (e) => {
e.target.classList.remove('moving')
}3. FLIP animation
FLIP animation is another fun piece. I won't dive too deep here — I'll sketch the idea, and the full code is in the code block below.
The idea:
FLIP (First, Last, Invert, Play) is an animation optimization technique for smooth animations and better performance.
-
First: before the animation starts, capture the element's initial state (position, size, etc.).
-
Last: based on the final animation state, compute the element's target position, size, etc.
-
Invert: apply the last frame's state to the element, using CSS or JavaScript to position it directly at the final state — this
avoids triggering layout reflow during the animation. (In short: compute the offset.) -
Play: add a CSS transition or animation to move the element from the first frame state to the last frame state, producing a smooth animation.
Full code: https://code.juejin.cn/pen/7282991337383657511
4. Wrap-up
Quick recap. Two main ideas, both very common in practice:
-
Drag-and-drop sorting
-
FLIP animation
Recommended:
Happy Mid-Autumn Festival and National Day, everyone!