Drag and Drop en HTML5 y JavaScript: Guía Completa con Ejemplos Reales

- 👤 Andrés Cruz

🇺🇸 In english

Drag and Drop en HTML5 y JavaScript: Guía Completa con Ejemplos Reales

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 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

Drag and drop ejemplo básico

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.

Una aplicación debe ser intuitiva, y que más intuitivo que arrastrar un "objeto" de una parte a otra.

¿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.

Para crear elementos arrastrables ya no es necesario usar un plugin para llevar a cabo dicha tarea, usando HTML o mejor dicho HTML5 con JavaScript nativo podremos realizar Drag and Drop sobre todos los elementos que queremos.

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).

Además en este evento podemos definir un estilo personalizado al elemento que está siendo arrastrado.

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.

Este evento es muy útil para saber en todo momento el estado del elemento arrastrable; por ejemplo, para saber la posición exacta del elemento.

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.

Los atributos que colocamos en los elementos son: ondragstar, ondrag y ondragend respectivamente.

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-.

Este evento es ideal para cambiar las reglas de estilo del contenedor al estar "dentro" del elemento arrastrable.

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.

este evento es perfecto para eliminar cualquier estilo aplicado a nuestro 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.

Los atributos que colocamos en los elementos son: ondragenter, ondragleave, ondragover y ondrop respectivamente.

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.

Cualquier elemento del DOM puede ser arrastrable.

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...

...¿Cómo enviamos los datos que están mantenidos en la operación del arrastrado?

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:

Drag and drop en Gmail

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

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.

| 👤 Andrés Cruz

🇺🇸 In english