This tutorial will guide you through the process of creating Javascript Draggable Sorting Tags. These tags are interactive elements that users can drag and rearrange within a container, offering a dynamic and user-friendly way to manage and organize items on a webpage. This functionality is particularly useful for features like playlist management, category sorting, or task prioritization, enhancing the overall user experience.
Setting Up the HTML Structure
First, you’ll need to create the basic HTML structure to house your draggable tags. This involves creating two `div` elements: one to act as a temporary container during the dragging process and another to hold the actual tags.
<div id="fake"></div>
<div id="container"></div>
<script src="./script.js"></script>
Styling with CSS
Now, let’s style these tags to make them visually appealing and interactive. The following CSS code provides a base style for the tags, including their appearance, positioning, and behavior on hover.
* {
box-sizing: border-box;
}
html, body {
height: 100%;
}
body {
background: #f3f8fc;
display: flex;
justify-content: center;
align-items: center;
}
#container {
display: flex;
position: absolute;
}
.block {
display: flex;
align-items: center;
background: linear-gradient(to bottom, white, #e0ecf0);
border-radius: 1000px;
font-weight: 500;
cursor: pointer;
padding: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.1), inset 0 -1px 0 0 rgba(0, 0, 0, 0.1), inset 0 1px 0 0 rgba(255, 255, 255, 0.5);
user-select: none;
}
.block::before {
content: "";
display: block;
height: 12px;
width: 12px;
border-radius: 50%;
margin-right: 4px;
box-shadow: inset 0 1px 1px 0 rgba(0, 0, 0, 0.2), inset 0 1px 0 0 rgba(255, 255, 255, 0.6);
}
.strawberry::before {
background: tomato;
}
.watermelon::before {
background: pink;
}
.pear::before {
background: sandybrown;
}
.banana::before {
background: khaki;
}
.apple::before {
background: crimson;
}
.blueberry::before {
background: darkslateblue;
}
.pineapple::before {
background: yellow;
}
html, body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
color: rgba(0, 0, 0, 0.7);
}
#container.hidden {
visibility: hidden;
}
Implementing the Drag and Drop Functionality with JavaScript
This is where the magic happens! The following JavaScript code handles the drag-and-drop functionality. It captures mouse events, updates the tag positions in real-time, and smoothly transitions them to their new locations within the container.
const container = document.getElementById('container');
const fake = document.getElementById('fake');
const margin = 10;
let divs = ['apple','banana','pear','strawberry','watermelon','blueberry', 'pineapple'].map(txt => {
const d = document.createElement('div');
d.classList.add('block');
d.classList.add(txt);
Object.assign(d.style,{
margin: margin + 'px',
})
d.innerHTML = txt;
container.appendChild(d);
return d;
});
divs.forEach((d,startidx) => {
d.addEventListener('mousedown',()=>{
const x0 = container.getBoundingClientRect().x;
const y0 = container.getBoundingClientRect().y;
const others = divs.filter(d2 => d !== d2);
const positions = others.map(d => d.getBoundingClientRect().x);
const widths = others.map(d => d.getBoundingClientRect().width);
let moved = false;
let finalpos = d.getBoundingClientRect().x;
let finalidx = startidx;
const selfClone = d.cloneNode(true);
const clones = [];
function movedCBs(){
Object.assign(selfClone.style,{
left: d.getBoundingClientRect().x + 'px',
top: d.getBoundingClientRect().y + 'px',
position: 'fixed',
margin: 0,
'z-index': 2
})
fake.appendChild(selfClone);
container.classList.add('hidden');
others.forEach((d,i) => {
const position = positions[i];
const clone = d.cloneNode(true);
Object.assign(clone.style,{
position: 'fixed',
left: position + 'px',
top: y0 + margin + 'px',
transition: '.2s',
margin: 0,
})
fake.appendChild(clone);
clones.push(clone);
});
}
function transitionEnd(){
fake.innerHTML = '';
container.classList.remove('hidden');
d.parentNode.removeChild(d);
console.log(finalidx)
container.insertBefore(d, container.children[finalidx]);
divs = Array.from(container.children);
}
function move(e){
if (!moved){
movedCBs();
moved = true;
}
const posx = selfClone.getBoundingClientRect().x + e.movementX
Object.assign(selfClone.style,{
left: posx + 'px',
top: selfClone.getBoundingClientRect().y + e.movementY + 'px'
})
let pos = x0 + margin;
let counter;
let spliced = false;
for (counter=0; counter<widths.length; counter++){
const nextpos = pos + widths[counter] + margin*2;
if (!spliced && Math.abs(nextpos - posx) >= Math.abs(pos - posx)){
spliced = true;
finalpos = pos;
finalidx = counter;
}
Object.assign(clones[counter].style,{
left: pos + (spliced ? selfClone.getBoundingClientRect().width + margin*2 : 0) + 'px'
})
pos = nextpos;
}
if (!spliced){
finalpos = pos;
finalidx = counter;
}
}
document.addEventListener('mousemove', move );
document.addEventListener('mouseup', ()=>{
document.removeEventListener('mousemove',move);
if (!moved) return;
Object.assign(selfClone.style,{
transition: '.2s'
});
setTimeout(()=>{
Object.assign(selfClone.style,{
left: finalpos + 'px',
top: y0 + margin + 'px'
});
},0)
setTimeout(transitionEnd, 200)
},{once:true})
})
})
With these steps, you’ve successfully implemented Javascript Draggable Sorting Tags. This functionality allows users to interactively rearrange elements, providing a more engaging and intuitive experience.







