Drag and Drop en HTML5 y JavaScript: Guía Completa con Ejemplos Reales
- 👤 Andrés Cruz
El sistema de Drag and Drop (arrastrar y soltar) es una de esas funcionalidades que, bien implementadas, elevan la experiencia de usuario sin necesidad de librerías externas. Llevo años usándolo en proyectos reales (desde reorganizar listas de tareas hasta cargar archivos en interfaces conectadas a backends con Laravel o Django), y todavía me sorprende lo flexible que puede ser con solo HTML5 y JavaScript nativo.
En esta guía te explico todo, desde eventos hasta ejemplos avanzados, para que puedas implementar DnD en minutos y dominarlo en horas.
Antes vimos como generar archivos en JavaScript, al igual que leer y manipular.
Qué es el Drag and Drop y por qué es tan útil hoy
El Drag and Drop permite agarrar un elemento, moverlo y soltarlo en otro lugar. Aunque suena simple, es una de las interacciones más intuitivas para los usuarios.
Cómo funciona la interacción de arrastrar y soltar
Tres piezas clave:
- Elemento arrastrable (draggable)
- Datos a transferir (dataTransfer)
- Zona de destino (drop)
Las acciones en el Drag and Drop o Arrastras y Soltar son inmediatas: arrastras un archivo, lo sueltas, y voilà.
Casos de uso modernos
- Reordenar listas (tipo Kanban o to-do list).
- Lo uso en mis cursos y libros en donde implemento un backend con Laravel o Django para reorganizar tareas o listados en general.
- Construir interfaces estilo Trello o Gmail.
- Subir archivos arrastrándolos directamente a un contenedor.
- Mover imágenes entre galerías.
- Interfaces de backoffice con bloques reubicables.
Eventos del Drag and Drop: explicación clara y sin enredos
La API de arrastrar y soltar usa siete eventos clave, y eso es todo, con la practica los podrás conocer y hacer cosas realmente interesantes, veámoslo en términos generales:
- Eventos del arrastre
- dragstart: inicia el arrastre
- drag: se dispara repetidamente mientras se arrastra
- dragend: termina el arrastre
- Eventos del destino
- dragenter: el elemento arrastrable entra en la zona
- dragover: ocurre constantemente mientras está encima
- dragleave: se va de la zona
- drop: se suelta el elemento
- Errores típicos que rompen el DnD
- No poner event.preventDefault() en dragover.
- Esto bloquea el drop. Me pasó tantas veces que ya es un tic añadirlo.
- Modificar el DOM dentro de dragover.
- Afecta brutalmente al rendimiento.
- No poner event.preventDefault() en dragover.
No limpiar estilos en dragleave o dragend.
El Drag and Drop (Arrastrar y Soltar) es una característica que permite "agarrar" un objeto y arrastrarlo a una diferente localización

El Drag and Drop es uno de los grandes cambios que incorpora HTML5 es la característica de arrastrar y soltar (Drag and Drop) que puede ser aplicado a cualquier clase de elementos como contenedores (divs), textareas, párrafos, títulos, imágenes, etc.
El Drag and Drop es una herramienta poderosísima que permite llevar la interacción con el usuario a otro nivel que aprovecha sobre todo en esta "fiebre" que existe con los dispositivos móviles inteligentes como tablets o teléfonos que cuentan con una pantalla táctil que resulta en una combinación muy atractiva.
¿En qué consiste la característica de arrastrar y soltar?
Con el Drag and Drop simplemente llevamos un elemento de A a B "arrastrándolo" de un lado a otro (no solo aplica en HTML, todas las tecnologías que lo empleen -como Android- emplean el mismo principio).
Aunque al momento del desarrollo puede que no nos resulte tan sencillo sobre todo porque cuenta (al menos en la API de HTML5) con una cantidad importante de métodos, eventos y propiedades que nos permiten explotar esta tecnología al máximo.
Empezando con el Drag and Drop en HTML5
En esta entrega veremos algunas definiciones claves de cómo funciona esta tecnología, sus componentes, métodos, atributos, y varios ejemplos muy prácticos que seguro te resultan interesantes.
Eventos del Drag and Drop (JavaScript) - Drag
Los elementos arrastrables producen tres eventos:
1.0 dragstar()
Este evento es accionado cuando empezamos el arrastre de un elemento; en específico en este evento debemos especificar que es lo que estamos arrastrando y establecer los valores correspondientes mediante el método JavaScript setData; este evento solo es invocado una vez (al seleccionar el elemento).
2.0 drag()
Este evento es accionado inmediatamente después del método dragstar y ocurre cuando estamos arrastrando el elemento (tenemos el clic presionado sobre el elemento y no lo hemos soltado) y continuará mediante el "arrastrado" (drag) del mismo; el número de veces que se invoque este evento depende del navegador.
3.0 dragend()
Ocurre cuando terminamos de arrastrar el elemento y solo se ejecuta una vez; además es invocado independientemente de si el elemento es "soltado" dentro del contenedor o no.
Eventos del Drag and Drop (JavaScript) - Drop
El contenedor produce cuatro eventos:
1.0 dragenter()
Ocurre cuando empezamos a mover un elemento de tipo arrastrable dentro de su contenedor, pero todavía no ha sido soltado; en otras palabras, este evento se dispara cuando el elemento "arrastrable" entra dentro de la "zona para soltar" -drop zone-.
En este evento podemos inspeccionar la data transferida (dataTransfer) mediante el evento, esta data fue la inicializada mediante el método setData; además, podemos inspeccionar el tipo de dato devuelto.
2.0 dragleave()
Ocurre cuando un elemento arrastrable ha sido soltado/movido fuera del contenedor.
3.0 dragover()
Ocurre de manera continuamente cuando un elemento arrastrable se mueve dentro de su contenedor y solo se deja de ejecutar hasta que soltemos el elemento arrastrable dentro del contenedor o salgamos del mismo; este evento es perfecto para saber cual es la posición del elemento arrastrable dentro del contenedor.
Al igual que ocurre con el evento drag, es perfecto para determinar la posición exacta del elemento arrastrable debido a que se invoca repetidamente mientras que el elemento "arrastrable" esté dentro del contenedor; el número de veces que se invoque este evento depende del navegador.
4.0 drop()
Ocurre cuando un elemento arrastrable es soltado dentro de un contenedor; en este evento debemos recolectar la información del elemento arrastrable mediante el método getData.
Atributos del Drag and Drop en HTML5
Con sólo manejar los eventos no es suficiente para empezar a trabajar con el Drag and Drop en HTML5. Se debe añadir el atributo draggable="true" a los elementos del DOM que deseamos que sean arrastrables.
Hasta ahora se ha explicado cuáles eventos ocurren en el ciclo de vida del Drag and Drop; es decir cómo interactúan los elementos arrastrables con sus contenedores; pero...
Es decir; ¿cómo se determina que datos (que estamos arrastrando) tiene el elemento que está siendo arrastrados?; para eso utilizamos el siguiente objeto.
El objeto dataTransfer en el Drag and Drop (HTML5)
Simplemente arrastrando y soltando elementos a diestra y siniestra no es suficiente a menos que los datos que estamos moviendo se vean afectados; se utiliza este objeto para personalizar las operaciones del Drag and Drop; por ejemplo se emplea para establecer la información del evento arrastrable en el evento dragstart() y se procesa esta información en el evento drop(), veamos algunos de sus métodos más importantes:
.setData(formato, dato)Con este método debemos insertar la información que se desea guardar desde el elemento arrastrable (drag) y debe tener un tipo definido aunque debes estar pendiente con el soporte de los navegadores:
- Si vas a insertar texto: "text/plain".
- Si vas a insertar una url: "text/uri-list".
Esta información se debe establecer en el evento dragstar mediante event.datatransfer.setData(type, data).
Indicamos el tipo de dato (formato) a insertar ("Data", para cualquier tipo de dato) y el dato.
.getData(formato)Al contrario del método anterior, este nos devuelve la data recolectada establecida mediante el método setData.
Para recuperar la información se debe hacer solo en el evento drop() mediante event.dataTransfer.getData(type).
.clearData()Limpia todos los datos establecidos por el método setData(formato, dato) mediante event.dataTransfer.clearData(type).
En resumen, el cerebro del sistema es el objeto DataTransfer.
setData / getData
event.dataTransfer.setData("text/plain", elemento.id);const id = event.dataTransfer.getData("text/plain");
MIME types
- "text/plain"
- "text/html"
- "text/uri-list"
Imagen fantasma personalizada
event.dataTransfer.setDragImage(miImagen, 10, 10);Ejemplos prácticos paso a paso (código listo para usar)
Veamos una seria de ejemplos con los cuales, podrás conocer como utilizar la técnica de arrastrar y soltar y adaptar a tus desarrollos.
1.0 Ejemplo básico de Drag and Drop en HTML5 con el selector :after
Este es un ejemplo bastante básico en el cual empleamos los mínimos eventos necesarios para trabajar con el Drap and Drop.
Código completo (HTML y JavaScript)
function dragstart(caja, evento) {
// el elemento a arrastrar
event.dataTransfer.setData('Data', caja.id);
}
function drop(target, evento) {
// obtenemos los datos
var caja = event.dataTransfer.getData('Data');
// agregamos el elemento de arrastre al contenedor
target.appendChild(document.getElementById(caja));
}
Como vimos anteriormente, al empezar a arrastrar (se dispara el evento dragstart) indicamos la data a transferir mediante el método setData() y cuando el elemento arrastrable sea posicionado dentro del contenedor y soldado se dispara el último evento (drop) que lee la información transferida y lo copia dentro del contenedor.
Puedes ver el ejemplo completo en:
Cómo ves nos las ingeniamos para emplear el selector after para definir otro estilo variando el contenido (texto) de nuestro elemento arrastrable (caja) al estar dentro del contenedor.
2.0 Ejemplo básico de Drag and Drop en HTML5 con el selector :after y todos los eventos
Para conocer mejor cómo interactuar con todos los eventos, se presenta el mismo ejemplo presentado anteriormente pero esta vez definiremos soportados por el Drag and Drop en HTML5 y se mostrará un mensaje en la consola personalizado para cada uno:
Código JavaScript completo
function dragstart(caja, event) {
// el elemento a arrastrar
event.dataTransfer.setData('Data', caja.id);
}
function drag(target, event) {
console.log("drag");
return false;
}
function dragend(target, event) {
console.log("dragend");
return false;
}
function dragenter(target, event) {
console.log("dragenter");
return false;
}
function dragleave(target, event) {
console.log("dragleave");
return false;
}
function dragover(event) {
console.log("dragover");
event.preventDefault();
return false;
}
function drop(target, event) {
// obtenemos los datos
var caja = event.dataTransfer.getData('Data');
// agregamos el elemento de arrastre al contenedor
target.appendChild(document.getElementById(caja));
}
La descripción vista en el ejemplo anterior se aplica a este ejemplo; además como cotación adicional, verás múltiples eventos ejecutandose en la Consola de Desarrollador según posiciones el elemento arrastrable.
Puedes ver el ejemplo completo en:
3.0 Arrastrando y soltando archivos
Seguramente has empleado más de una vez la fantástica opción que ofrece Gmail para adjuntar archivos mediante el Drag and Drop:

Con HTML es realmente sencillo incorporar esta característica de Drag and Drop de archivos hacia una aplicación web:
Código JavaScript completo
var MAX_BYTES = 102400; // 100 KB
function dragenter(event) {
event.stopPropagation();
event.preventDefault();
}
function dragover(event) {
event.stopPropagation();
event.preventDefault();
}
function drop(event) {
console.log('drop', event);
event.stopPropagation();
event.preventDefault();
var data = event.dataTransfer;
var files = data.files;
var file;
var reader;
for (var i = 0; i < files.length; i++) {
file = files[i];
reader = new FileReader();
reader.onloadend = onFileLoaded;
reader.readAsBinaryString(file);
}
}
function onFileLoaded(event) {
document.getElementById("resultado").value = event.currentTarget.result.substr(0, MAX_BYTES);
}
var contenedor = document.getElementById("contenedor");
contenedor.addEventListener("dragenter", dragenter, false);
contenedor.addEventListener("dragover", dragover, false);
contenedor.addEventListener("drop", drop, false);
La API de archivos en JavaScript es tema de otra entrada y puedes verlo en el enlace anterior.
Puedes ver el ejemplo completo en:
4.0 Cambiando el estilo de los elementos con los eventos del Drag and Drop
Como último ejemplo veremos cómo variar el estilo de nuestros elementos empleando cada uno de los eventos existentes:
Código JavaScript completo
function dragstart(caja, event) {
// el elemento a arrastrar
document.getElementById(caja.id).className = "in";
event.dataTransfer.setData('Data', caja.id);
}
function drag(caja, event) {
return false;
}
function dragend(caja, event) {
document.getElementById(caja.id).className = "out";
return false;
}
function dragenter(target, event) {
document.getElementById("contenedor").className = "inContainer";
return false;
}
function dragleave(target, event) {
document.getElementById("contenedor").className = "outContainer";
return false;
}
function dragover(event) {
event.preventDefault();
return false;
}
function drop(target, event) {
// obtenemos los datos
var caja = event.dataTransfer.getData('Data');
document.getElementById("contenedor").className = "outContainer";
// agregamos el elemento de arrastre al contenedor
target.appendChild(document.getElementById(caja));
}
Puedes ver el ejemplo completo en:
5 Drag and Drop básico
<div id="origen" draggable="true">A</div>
<div id="destino"></div>
<script>
origen.addEventListener("dragstart", e => {
e.dataTransfer.setData("text/plain", e.target.id);
});
destino.addEventListener("dragover", e => e.preventDefault());
destino.addEventListener("drop", e => {
e.preventDefault();
const id = e.dataTransfer.getData("text/plain");
destino.appendChild(document.getElementById(id));
});
</script>6 Carga de archivos arrastrando desde el escritorio
Este es uno de los casos más prácticos, con esto, al ocurrir el evento drop con el archivo, lo obtiene y lo envías por fetch o donde quieras.
contenedor.addEventListener("dragover", e => e.preventDefault());
contenedor.addEventListener("drop", e => {
e.preventDefault();
const archivos = e.dataTransfer.files;
for (const file of archivos) {
console.log("Archivo:", file.name);
// Subida del archivo vía AJAX / fetch
}
});Cómo mejorar la experiencia visual del usuario
- Estilos dinámicos con dragenter/dragleave
zona.addEventListener("dragenter", () => zona.classList.add("over")); zona.addEventListener("dragleave", () => zona.classList.remove("over"));
- Indicadores visuales
- Bordes punteados, resaltado de fondo, iconos de acción.
- Microinteracciones
- Transiciones de 100–200ms hacen maravillas.
Drag and Drop en móvil y pantallas táctiles
El DnD nativo no funciona igual en móviles.
- Limitaciones
- Eventos drag no siempre se disparan
- La imagen fantasma no aparece
- Movemento dependiente del sistema táctil
- Soluciones
- Combinar con eventos touchstart, touchmove, touchend
- O usar librerías: SortableJS, InteractJS, Dragula
- Mantener la experiencia fluida
En apps donde uso Laravel o Django para backend, suelo mezclar tacto + DnD nativo para mantener un mismo flujo en escritorio y móvil.
Optimización y rendimiento en operaciones de arrastre
- Minimizar repintados
- Evita modificar estilos dentro de dragover.
- Delegación de eventos
- Maneja arrastres desde un único listener.
- Recomendaciones reales
- throttling
- evitar DOM pesado
- usar transformaciones CSS para mover elementos
Seguridad y manejo seguro de datos en DnD
- Sanitización
- Si usas HTML en dataTransfer, sanitiza siempre.
- Prevención de fugas
- Nunca transfieras tokens o IDs sensibles.
- DnD y archivos
- Valida:
- tamaño
- extensión
- tipo MIME
- Valida:
En mis cargas con arrastrar-soltar para backend, siempre valido tamaño antes de enviar al servidor.
Conclusión
En esta un poco extensa introducción a el Drag and Drop con HTML5 vimos como crear nuestro propio sistema de Drag and Drop y múltiples ejemplo que evidencia el uso de los distintos eventos y varios casos de prueba de lo más útiles como el que permite obtener archivos desde el computador.
Además vimos que el gran número de eventos que maneja no es un inconveniente sino todo lo contrario que permiten obtener datos en todo momento del estado tanto del elemento arrastrable como contenedor y personalizar estas acciones casi que a un 100%.
El Drag and Drop en HTML5/JS sigue siendo una herramienta potente, flexible y moderna. Con unos pocos eventos puedes crear interfaces avanzadas, desde tableros tipo Trello hasta módulos de carga de archivos.
Checklist rápido
- draggable="true"
- Eventos: dragstart / dragend / dragenter / dragover / dragleave / drop
- event.preventDefault() en dragover
- Usar DataTransfer correctamente
- Feedback visual claro
- Accesibilidad y compatibilidad móvil
Cuándo usar librerías
- Proyectos grandes o muy dinámicos
- Reordenamiento complejo
- Necesidad de soporte móvil perfecto
Aprende ahora a como copiar y pegar con SOLO JavaScript.
Acepto recibir anuncios de interes sobre este Blog.
Drag and Drop (Arrastrar y Soltar) es una característica que permite "agarrar" un objeto, arrastrarlo y soltarlo en una diferente localización. En en esta entrada hablaremos sobre el Drag and Drop en HTML5, ejemplos, métodos y atributos.