Hi! I'm back after a long break with a new post on how to create a Drag and Drop interface using Vanilla JS.
Let's have look what we are going to create in this tutorial
Drag and drop functionality is a great way to enhance the user experience of a web application. With drag and drop, users can easily move elements around a page, reorder lists, and perform other interactive actions. In this tutorial, we'll cover how to create a simple drag and drop interface with vanilla JavaScript.
We'll be using TailwindCSS for styling you may use pure CSS or any other CSS framework.
So, let's write the HTML for our project in index.html
HTML
<html>
<head>
<title>Drag and Drop Example</title>
</head>
<body>
<ul id="list">
<li id="item1" draggable="true">Item 1</li>
<li id="item2" draggable="true">Item 2</li>
<li id="item3" draggable="true">Item 3</li>
<li id="item4" draggable="true">Item 4</li>
<li id="item5" draggable="true">Item 5</li>
</ul>
<div id="target"></div>
</body>
</html>
Now add the Tailwind CDN in <head>
and add classes to it
<!DOCTYPE html>
<html>
<head>
<title>Drag and Drop Example</title>
<!-- Load Tailwind CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.7/tailwind.min.css">
<style>
/* Add custom styles here */
</style>
</head>
<body class="bg-gray-100">
<div class="max-w-md mx-auto mt-8">
<!-- Drag and drop list -->
<div class="p-4 bg-white rounded-lg shadow-lg">
<ul id="list" class="list-none p-0 m-0 bg-gray-100 border border-gray-300 min-h-40">
<li id="item1" draggable="true" class="bg-white border border-gray-300 p-4 mb-2 cursor-move">Item 1</li>
<li id="item2" draggable="true" class="bg-white border border-gray-300 p-4 mb-2 cursor-move">Item 2</li>
<li id="item3" draggable="true" class="bg-white border border-gray-300 p-4 mb-2 cursor-move">Item 3</li>
<li id="item4" draggable="true" class="bg-white border border-gray-300 p-4 mb-2 cursor-move">Item 4</li>
<li id="item5" draggable="true" class="bg-white border border-gray-300 p-4 mb-2 cursor-move">Item 5</li>
</ul>
</div>
<!-- Drop target -->
<div id="target" class="mt-4 p-4 bg-white rounded-lg shadow-lg border-dashed border-2 border-gray-300 min-h-60">
<p class="text-center text-gray-400">Drop items here</p>
</div>
</div>
<script src="index.js"></script>
</body>
</html>
Now create index.js
and add this to index.html
JavaScript:-
Now write some JS for our drag and drop interface.
const listItems = document.querySelectorAll("#list li");
const target = document.querySelector("#target");
for (const listItem of listItems) {
listItem.addEventListener("dragstart", dragStart);
}
target.addEventListener("dragover", dragOver);
target.addEventListener("drop", drop);
function dragStart(event) {
event.dataTransfer.setData("text/plain", event.target.id);
}
function dragOver(event) {
event.preventDefault();
target.classList.add("border-gray-500");
}
function drop(event) {
event.preventDefault();
const itemId = event.dataTransfer.getData("text/plain");
const item = document.getElementById(itemId);
target.appendChild(item);
target.classList.remove("border-gray-500");
}
Code Explanation:-
First, it selects all the list items on the page and the target element using document.querySelectorAll
and document.querySelector
. This is done using CSS selectors: #list li
selects all the li
elements inside the element with the ID list
, and #target
selects the element with the ID target
.
Next, it adds a dragstart
event listener to each list item using a for...of
loop. This event listener is triggered when the user starts dragging an item.
The dragStart
function is called when the event is triggered. It sets the data that is being dragged by calling event.dataTransfer.setData("text/plain", event.target.id)
. The first argument specifies the data type (text/plain
in this case), and the second argument is the ID of the element being dragged.
The code then adds a dragover
event listener to the target element. This event listener is triggered when the user drags an item over the target element.
The dragOver
function is called when the event is triggered. It calls event.preventDefault()
to allow the drop
event to be triggered. It also adds a CSS class to the target element to indicate that it can be dropped onto.
Finally, the code adds a drop
event listener to the target element. This event listener is triggered when the user drops an item onto the target element.
The drop
function is called when the event is triggered. It calls event.preventDefault()
to prevent the default behavior (which is to navigate to a new page). It then gets the ID of the element being dragged by calling event.dataTransfer.getData("text/plain")
. It retrieves the element by its ID using document.getElementById(itemId)
, and appends it to the target element using target.appendChild(item)
. Finally, it removes the CSS class that was added to the target element in the dragOver
function.
Finally the Drag and Drop Interface is ready.
I hope you loved this.
Let's connect:
Top comments (21)
Nice. An excellent and clear explanation, sadly somewhat diminished by the inclusion of the irrelevant Tailwind dependency, as if we can do vanilla JS, but not vanilla CSS. Ironic.
Note: your JS is improperly formatted and initially I thought that lines 2-26 were inside a function. Took me a moment. Maybe remove the indent?
Definitely one of the clearest and most useful posts I've seen here in a while.
Thanks Charles for your feedback and pointing out the formatting issue ,it's been fixed now.
And for not using Vanilla CSS, I'll say, for a long time I'm not using vanilla CSS instead of that I'm using Tailwind CSS but from the next time I'll definitely use vanilla CSS with vanilla JS.
Cool. I'm using Astro and TypeScript to generate vanilla JS/CSS/HTML -- no browser-side dependencies at all, but I still get types and components.
Very well explained rohit 👍👍
Thanks Kalpit..
Great code and explanation
Thanks Dprincecoder
Very nice post👍🏼
I remember struggling with this feature on an image processing app some months ago.
Thanks Michael
Nice sir 👍
Thanks Amir
Good work. But right inside the Dropbox, can the text in each box be edited? I'm looking at a scenario where the boxes are list of products, then, after drag n drop, users can edit each quantity of product, to get a new combo. Please, I'll need your help or advice on this, if you understand it. Thanks.
well explained, but does this not work on mobile?
Well, this is working on my mobile.
You just need to long press on the draggable then you'll be able to drag it.
Try this way, Hope it will work.
Ah it does, this is great!
Thanks Medea
Thank you for this article..
Cool little feature and very nicely explained. I hope to use something based on this one day! Thanks!
Thank you for your kind words! I'm glad you found the feature and explanation helpful.