HTML5 Drag and Drop API
The Drag and Drop API allows users to drag elements and drop them onto other elements. It's useful for file uploads, sortable lists, kanban boards, and interactive interfaces.
Making Elements Draggable
Add the draggable="true" attribute to make an element draggable.
By default, images and links are draggable; other elements are not.
Handle the dragstart event to set data being dragged.
Use the dataTransfer object to transfer data during drag operations.
The effectAllowed property specifies allowed drag operations (copy, move, link).
<!-- Draggable element -->
<div draggable="true" ondragstart="drag(event)" id="draggable">
Drag me!
</div>
<!-- Drop target -->
<div ondrop="drop(event)" ondragover="allowDrop(event)"
style="width: 200px; height: 200px; border: 2px dashed #ccc;">
Drop here
</div>
<script>
function drag(event) {
// Set data being dragged
event.dataTransfer.setData('text/plain', event.target.id);
event.dataTransfer.effectAllowed = 'move';
}
function allowDrop(event) {
event.preventDefault(); // Must prevent default to allow drop
}
function drop(event) {
event.preventDefault();
const data = event.dataTransfer.getData('text/plain');
const dragged = document.getElementById(data);
event.target.appendChild(dragged);
}
</script>
Drag Events
dragstart: Fired when dragging begins.
drag: Fired continuously while dragging.
dragend: Fired when dragging ends (whether successful or cancelled).
dragenter: Fired when dragged item enters a drop target.
dragover: Fired continuously while dragging over a drop target.
dragleave: Fired when dragged item leaves a drop target.
drop: Fired when item is dropped on a valid drop target.
<div draggable="true" id="item"
ondragstart="handleDragStart(event)"
ondrag="handleDrag(event)"
ondragend="handleDragEnd(event)">
Drag Item
</div>
<div id="dropzone"
ondragenter="handleDragEnter(event)"
ondragover="handleDragOver(event)"
ondragleave="handleDragLeave(event)"
ondrop="handleDrop(event)"
style="width: 300px; height: 200px; border: 2px solid black;">
Drop Zone
</div>
<script>
function handleDragStart(e) {
e.dataTransfer.setData('text/plain', e.target.id);
e.target.style.opacity = '0.5';
}
function handleDragEnd(e) {
e.target.style.opacity = '1';
}
function handleDragEnter(e) {
e.target.style.backgroundColor = '#e0f7fa';
}
function handleDragOver(e) {
e.preventDefault(); // Required
e.dataTransfer.dropEffect = 'move';
}
function handleDragLeave(e) {
e.target.style.backgroundColor = '';
}
function handleDrop(e) {
e.preventDefault();
e.target.style.backgroundColor = '';
const id = e.dataTransfer.getData('text/plain');
const item = document.getElementById(id);
e.target.appendChild(item);
}
</script>
Drag and Drop for File Upload
The dataTransfer.files property contains files dragged from the desktop.
Handle the drop event to access dropped files.
Use FileReader API to read file contents.
Validate file types and sizes before processing.
Provide visual feedback during drag operations.
<div id="fileDropZone"
ondrop="handleFileDrop(event)"
ondragover="event.preventDefault()"
ondragenter="this.style.backgroundColor='#e8f5e9'"
ondragleave="this.style.backgroundColor=''"
style="width: 400px; height: 200px; border: 3px dashed #666;
display: flex; align-items: center; justify-content: center;">
<p>Drag and drop files here</p>
</div>
<div id="fileList"></div>
<script>
function handleFileDrop(event) {
event.preventDefault();
event.target.style.backgroundColor = '';
const files = event.dataTransfer.files;
const fileList = document.getElementById('fileList');
fileList.innerHTML = '<h3>Dropped Files:</h3>';
for (let file of files) {
// Validate file
if (file.size > 5 * 1024 * 1024) { // 5MB limit
alert(`File ${file.name} is too large (max 5MB)`);
continue;
}
const fileInfo = document.createElement('p');
fileInfo.textContent = `${file.name} (${(file.size / 1024).toFixed(1)} KB)`;
fileList.appendChild(fileInfo);
// Read file if it's an image
if (file.type.startsWith('image/')) {
const reader = new FileReader();
reader.onload = function(e) {
const img = document.createElement('img');
img.src = e.target.result;
img.style.maxWidth = '200px';
fileList.appendChild(img);
};
reader.readAsDataURL(file);
}
}
}
</script>
Sortable List Example
Drag and drop is perfect for creating sortable lists.
Track which element is being dragged and where it's being dropped.
Reorder DOM elements based on drop position.
Provide visual feedback with CSS during dragging.
Use data attributes or IDs to track list items.
<ul id="sortable" style="list-style: none; padding: 0;">
<li draggable="true" class="sortable-item">Item 1</li>
<li draggable="true" class="sortable-item">Item 2</li>
<li draggable="true" class="sortable-item">Item 3</li>
<li draggable="true" class="sortable-item">Item 4</li>
</ul>
<style>
.sortable-item {
padding: 10px;
margin: 5px 0;
background: #f0f0f0;
border: 1px solid #ccc;
cursor: move;
}
.sortable-item.dragging {
opacity: 0.5;
}
.sortable-item.drag-over {
border-top: 3px solid blue;
}
</style>
<script>
let draggedItem = null;
document.querySelectorAll('.sortable-item').forEach(item => {
item.addEventListener('dragstart', function() {
draggedItem = this;
this.classList.add('dragging');
});
item.addEventListener('dragend', function() {
this.classList.remove('dragging');
});
item.addEventListener('dragover', function(e) {
e.preventDefault();
this.classList.add('drag-over');
});
item.addEventListener('dragleave', function() {
this.classList.remove('drag-over');
});
item.addEventListener('drop', function(e) {
e.preventDefault();
this.classList.remove('drag-over');
if (draggedItem !== this) {
const allItems = [...document.querySelectorAll('.sortable-item')];
const draggedIndex = allItems.indexOf(draggedItem);
const droppedIndex = allItems.indexOf(this);
if (draggedIndex < droppedIndex) {
this.parentNode.insertBefore(draggedItem, this.nextSibling);
} else {
this.parentNode.insertBefore(draggedItem, this);
}
}
});
});
</script>