The HTML5 Drag and Drop API offers a simple method for allowing the movement of HTML objects around a webpage. In the past, this typically involved some pretty complex JavaScript and even then, not every browser was sure to support the proper offsets and such.
If curious though, you can check out my article showing how to implement custom drag and drop functionality in JavaScript.
Lucky for us, JavaScript is continuously getting updated with new API's that solve many of these older challenges and you can have elements floating around with just a few lines of code, which I'll go through down below.
Use cases
Before we start though, here are a few use cases where it might make sense to add drag and drop functionality, because you also don't want to make elements draggable for no reason, as that could effect usability and accessibility down the line.
- Rearrange items in a list
- Upload files by dragging them to a dropzone
- Drag based games and other interactive applications
- Kanban style boards
But really, anything where it makes sense to have an element in one location appear in another in the least amount of moves.
Example
Here is a quick example of a draggable element using this API:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Basic Drag and Drop</title>
<style>
.draggable {
width: 100px;
height: 100px;
background-color: #3498db;
color: white;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
margin-bottom: 10px;
}
.dropzone {
width: 200px;
height: 200px;
border: 2px dashed #ccc;
display: flex;
justify-content: center;
align-items: center;
color: #ccc;
}
</style>
</head>
<body>
<div class="draggable" draggable="true" id="draggableElement">Drag me</div>
<div class="dropzone" id="dropzone">Drop here</div>
<script>
const draggableElement = document.getElementById('draggableElement');
const dropzone = document.getElementById('dropzone');
draggableElement.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', draggableElement.id);
});
dropzone.addEventListener('dragover', (e) => {
e.preventDefault();
});
dropzone.addEventListener('drop', (e) => {
e.preventDefault();
const draggedElementId = e.dataTransfer.getData('text');
const draggedElement = document.getElementById(draggedElementId);
dropzone.appendChild(draggedElement);
dropzone.style.border = '2px solid #3498db';
});
</script>
</body>
</html>
And that would render the following:
Drag me
Drop here
Code breakdown
Let's start with the markup shown above:
<div class="draggable" draggable="true" id="draggableElement">Drag me</div>
<div class="dropzone" id="dropzone">Drop here</div>
The key component here is adding the draggable attribute to the object that we want to be moved around. This attribute takes in a Boolean value of true or false, meaning that we could technically turn on/off draggability using JavaScript if we needed to.
The dropzone itself is just an ordinary <div> element that's spacious enough to accommodate the dragged object.
Next up, let's take a look at some of the event handlers, starting with the one that starts the chain of events dragstart.
draggableElement.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', draggableElement.id);
});
This event fires as soon as a draggable element is clicked down to begin its movement. The code itself isn't anything too special, as all it does is it stores the draggable elements ID in the dataTransfer object.
We'll use this ID later on during the drop event. Next up, the dragover event. This event fires when a draggable element is hovering over a selected dropzone.
dropzone.addEventListener('dragover', (e) => {
e.preventDefault();
});
By default, dropping an element is disabled on the selected dropzone. This is why we're using the e.preventDefault() method in order to override the default behavior.
And once our draggable element is over the dropzone, then we need to handle the drop event.
dropzone.addEventListener('drop', (e) => {
e.preventDefault();
const draggedElementId = e.dataTransfer.getData('text');
const draggedElement = document.getElementById(draggedElementId);
dropzone.appendChild(draggedElement);
dropzone.style.border = '2px solid #3498db';
});
The first thing that we need to do, is to call the preventDefault() method as well in order to override the dropzones default behavior.
Next up, we can use the dataTransfer.getData method in order to retrieve the ID of the element that is being dropped.
And lastly, we simply call the appendChild method on the dropzone in order to change the parent of the draggable object.
While the default drag-and-drop behavior works, the appearance of the dragged element can be customized. One way to enhance the UX is by using custom drag previews. This allows users to see a visual representation of what they're dragging.
Cross-Browser Compatibility
While the HTML5 Drag and Drop API is widely supported, there are some browser-specific quirks to watch out for:
The API is primarily designed for desktop browsers. For mobile devices, you may need to use touch events for a comparable drag-and-drop experience.
Ensure that data transferred between drag-and-drop elements is in a supported format like text or text/plain. Some browsers might not support custom types.
The HTML5 Drag and Drop API offers a flexible and lightweight solution for adding interactivity to your web apps. From simple draggable elements to complex interfaces like kanban boards, the API can be adapted to suit many use cases.