Free Web Design Code & Scripts

JavaScript Draggable Sorting Tags

Javascript Draggable Sorting Tags
Code Snippet:Drag to reorder tags
Author: Grant
Published: 2 months ago
Last Updated: November 23, 2025
Downloads: 82
License: MIT
Edit Code online: View on CodePen
Read More

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.

Loading... ...

Loading preview...

Device: Desktop
Dimensions: 1200x800
Lines: 0 Characters: 0 Ln 1, Ch 1

Leave a Comment

About W3Frontend

W3Frontend provides free, open-source web design code and scripts to help developers and designers build faster. Every snippet is reviewed before publishing for quality. Learn more.