hace 7 años
El Drag and Drop, o arrastrar y soltar, es una funcionalidad interactiva y muy intuitiva que permite a los usuarios mover elementos de una ubicación a otra en una interfaz web de manera sencilla. Con solo hacer clic, mantener presionado el botón del ratón sobre un elemento, arrastrarlo y soltarlo en una nueva posición, se abre un mundo de posibilidades para mejorar la experiencia del usuario en nuestras aplicaciones web.

- ¿Qué es Drag and Drop en HTML5?
- Implementando Drag and Drop en HTML: Paso a Paso
- Ejemplos Prácticos de Drag and Drop en HTML
- Navegadores Compatibles
- ¿Qué es un Evento de Drag and Drop en Detalle?
- Haciendo un Elemento Arrastrable en HTML5: Enfoque Alternativo
- Preguntas Frecuentes (FAQ) sobre Drag and Drop en HTML5
- Conclusión
¿Qué es Drag and Drop en HTML5?
HTML5 introdujo soporte nativo para Drag and Drop, simplificando enormemente su implementación. Antes, lograr esta interactividad requería de complejas soluciones con JavaScript. Ahora, con HTML5, podemos añadir esta funcionalidad a cualquier elemento con unas pocas líneas de código y aprovechando los eventos integrados del navegador.

Eventos Clave en Drag and Drop
La magia del Drag and Drop se basa en una serie de eventos que se disparan durante la operación. Comprender estos eventos es crucial para implementar correctamente esta funcionalidad. A continuación, detallamos los eventos más importantes:
- dragstart: Se dispara al inicio de la operación de arrastre. Es el evento que indica que el usuario ha comenzado a arrastrar un elemento.
- drag: Se dispara repetidamente mientras el elemento está siendo arrastrado. Permite realizar acciones de manera continua durante el arrastre.
- dragenter: Se dispara cuando el elemento arrastrado entra en la zona de un posible destino de soltado.
- dragleave: Se dispara cuando el elemento arrastrado sale de la zona de un posible destino de soltado, o del destino de soltado actual.
- dragover: Se dispara constantemente mientras el elemento arrastrado se encuentra sobre un posible destino de soltado. Es fundamental para permitir que un elemento sea un destino de soltado válido.
- drop: Se dispara cuando el usuario suelta el botón del ratón sobre un destino de soltado válido. Este es el evento que finaliza la operación de arrastre y soltado.
- dragend: Se dispara al finalizar la operación de arrastre, independientemente de si se ha soltado el elemento en un destino válido o no.
El Objeto DataTransfer: El Corazón del Drag and Drop
El objeto dataTransfer es esencial en las operaciones de Drag and Drop. Actúa como un contenedor de datos que se transfieren durante el proceso de arrastre. Permite definir qué datos se arrastran y cómo se manejan al soltar el elemento. Aquí te presentamos las propiedades y métodos más relevantes de este objeto:
| Propiedad/Método | Descripción |
|---|---|
dataTransfer.setData(formato, datos) | Establece los datos que se van a arrastrar. Requiere especificar un formato (ej: 'text/plain', 'text/html') y los datos en sí. |
dataTransfer.clearData(formato) | Elimina los datos asociados a un formato específico. Si no se especifica el formato, elimina todos los datos. |
dataTransfer.getData(formato) | Recupera los datos asociados a un formato específico. Retorna una cadena vacía si no hay datos para ese formato. |
dataTransfer.types | Retorna un array con todos los formatos de datos establecidos durante el evento dragstart. |
dataTransfer.files | Retorna una lista de archivos que se están arrastrando (útil para la carga de archivos mediante Drag and Drop). |
dataTransfer.setDragImage(elemento, x, y) | Permite definir una imagen personalizada que se mostrará durante el arrastre, en lugar de la imagen fantasma por defecto del navegador. Se pueden especificar las coordenadas (x, y) del punto de anclaje de la imagen con respecto al cursor. |
dataTransfer.addElement(elemento) | Añade un elemento HTML como imagen de retroalimentación durante el arrastre. |
dataTransfer.effectAllowed | Define las operaciones permitidas durante el arrastre por parte del usuario (ej: 'none', 'copy', 'link', 'move', etc.). Influye en el cursor que se muestra durante el arrastre. |
dataTransfer.dropEffect | Controla la retroalimentación visual que se muestra al usuario durante los eventos dragenter y dragover, indicando el tipo de operación que se realizará al soltar (ej: 'none', 'copy', 'link', 'move'). |
Implementando Drag and Drop en HTML: Paso a Paso
A continuación, te guiaremos a través de los pasos necesarios para implementar la funcionalidad Drag and Drop en tus proyectos HTML:
Hacer un Elemento Arrastrable
El primer paso es indicar al navegador qué elementos deben ser arrastrables. Esto se logra añadiendo el atributo
draggable="true"al elemento HTML deseado.<img draggable="true" src="imagen.png"> <div draggable="true" id="miDivArrastrable">Este div se puede arrastrar</div>Definir el Comportamiento del Arrastre (dragstart)
El evento
dragstartes crucial para definir qué datos se van a arrastrar y cómo se inicia la operación. Normalmente, se utiliza JavaScript para manejar este evento y configurar el objetodataTransfer.function iniciarArrastre(evento) { evento.dataTransfer.setData("text/plain", evento.target.id); // Establecer el ID del elemento como dato arrastrado // Opcionalmente, personalizar la imagen de arrastre: // evento.dataTransfer.setDragImage(miImagenPersonalizada, 10, 10); } // Asignar el evento ondragstart al elemento arrastrable en HTML: <div draggable="true" id="elementoOrigen" ondragstart="iniciarArrastre(event)">Arrastrar este div</div>Habilitar un Elemento como Destino de Soltado (dragover)
Por defecto, la mayoría de los elementos HTML no aceptan elementos soltados. Para que un elemento se convierta en un destino de soltado, debemos manejar el evento
dragovery prevenir el comportamiento predeterminado del navegador utilizandoevento.preventDefault().function permitirSoltar(evento) { evento.preventDefault(); // ¡Importante! Permite que se produzca el 'drop' // Opcionalmente, modificar el cursor o la retroalimentación visual: // evento.dataTransfer.dropEffect = 'move'; } // Asignar el evento ondragover al elemento destino en HTML: <div id="zonaDestino" ondragover="permitirSoltar(event)">Zona de destino</div>Manejar el Soltado (drop)
El evento
dropse dispara cuando el usuario suelta el elemento arrastrado sobre un destino válido. En este evento, se debe implementar la lógica para procesar los datos arrastrados y realizar la acción deseada (ej: mover el elemento, copiarlo, etc.).function soltarElemento(evento) { evento.preventDefault(); // Prevenir el comportamiento predeterminado del navegador const datosArrastrados = evento.dataTransfer.getData("text/plain"); // Obtener los datos arrastrados (en este caso, el ID del elemento) const elementoArrastrado = document.getElementById(datosArrastrados); const zonaDestino = evento.target; zonaDestino.appendChild(elementoArrastrado); // Mover el elemento arrastrado a la zona de destino // Otra lógica posible: copiar el elemento, realizar una acción con los datos, etc. } // Asignar el evento ondrop al elemento destino en HTML: <div id="zonaDestino" ondragover="permitirSoltar(event)" ondrop="soltarElemento(event)">Zona de destino</div>
Ejemplos Prácticos de Drag and Drop en HTML
Para consolidar lo aprendido, veamos algunos ejemplos concretos que ilustran la implementación de Drag and Drop en HTML.
1. Arrastrar y Soltar una Imagen
Este ejemplo muestra cómo permitir al usuario arrastrar una imagen y soltarla dentro de un área rectangular.

<!DOCTYPE HTML> <html> <head> <style> #zonaDeSoltado { width: 250px; height: 200px; padding: 10px; border: 1px solid #4f4d4d; } </style> <script> function permitirSoltar(evento) { evento.preventDefault(); } function iniciarArrastre(evento) { evento.dataTransfer.setData("text", evento.target.id); } function soltarElemento(evento) { evento.preventDefault(); var datosArrastrados = evento.dataTransfer.getData("text"); evento.target.appendChild(document.getElementById(datosArrastrados)); } </script> </head> <body> <h3>Arrastra la imagen de GeekforGeeks al rectángulo:</h3> <div id="zonaDeSoltado" ondrop="soltarElemento(event)" ondragover="permitirSoltar(event)"> </div> <br> <img id="imagenArrastrable" src="gfg.png" draggable="true" ondragstart="iniciarArrastre(event)" width="250" height="200"> </body> </html>2. Propiedad draggable en Acción: Cajas Arrastrables
Este ejemplo demuestra cómo hacer arrastrables varios elementos div y permite moverlos entre diferentes zonas de soltado.
<!DOCTYPE HTML> <html> <head> <title>Drag and Drop de Cajas</title> <script> function permitirSoltar(evento) { evento.preventDefault(); } function iniciarArrastre(evento) { evento.dataTransfer.setData("text", evento.target.id); } function soltarElemento(evento) { evento.preventDefault(); let datosArrastrados = evento.dataTransfer.getData("text"); evento.target.appendChild(document.getElementById(datosArrastrados)); } </script> <style> #contenedorCajas { margin: auto; width: 50%; height: 200px; border: 3px solid green; padding: 10px; } #caja1, #caja2, #caja3 { float: left; margin: 5px; padding: 10px; } #caja1 { width: 50px; height: 50px; background-color: #F5B5C5; } #caja2 { width: 100px; height: 100px; background-color: #B5D5F5; } #caja3 { width: 150px; height: 150px; background-color: #BEA7CC; } p { font-size: 20px; font-weight: bold; text-align: center; } .gfg { font-size: 40px; color: #009900; font-weight: bold; text-align: center; } </style> </head> <body> <div class="gfg">GeeksforGeeks</div> <p>Arrastrar y soltar cajas</p> <div id="contenedorCajas"> <div id="caja1" draggable="true" ondragstart="iniciarArrastre(event)"></div> <div id="caja2" draggable="true" ondragstart="iniciarArrastre(event)"></div> <div id="caja3" ondrop="soltarElemento(event)" ondragover="permitirSoltar(event)"></div> </div> </body> </html>3. Drag and Drop de Imágenes entre Contenedores
Este ejemplo muestra cómo arrastrar imágenes entre diferentes contenedores div, creando una interfaz interactiva para organizar visualmente elementos.
<!DOCTYPE HTML> <html> <head> <script> function permitirSoltar(evento) { evento.preventDefault(); } function iniciarArrastre(evento) { evento.dataTransfer.setData("text", evento.target.id); } function soltarElemento(evento) { evento.preventDefault(); var datosArrastrados = evento.dataTransfer.getData("text"); evento.target.appendChild(document.getElementById(datosArrastrados)); } </script> <style> .div1 { width: 240px; height: 75px; padding: 10px; border: 1px solid black; background-color: #F5F5F5; } p { font-size: 20px; font-weight: bold; } .gfg { font-size: 40px; color: #009900; font-weight: bold; } </style> </head> <body> <div class="gfg">GeeksforGeeks</div> <p>Drag and Drop de Imágenes en cajas</p> <div class="div1" ondrop="soltarElemento(event)" ondragover="permitirSoltar(event)"> <img id="imagenArrastrable1" src="https://media.geeksforgeeks.org/wp-content/cdn-uploads/Geek_logi_-low_res.png" draggable="true" ondragstart="iniciarArrastre(event)" width="220" height="70"> </div> <br> <div class="div1" ondrop="soltarElemento(event)" ondragover="permitirSoltar(event)"> </div> </body> </html>4. Arrastrando Texto en un Rectángulo
Este ejemplo muestra cómo permitir al usuario arrastrar texto desde un párrafo y soltarlo dentro de un área rectangular, demostrando la flexibilidad del Drag and Drop con diferentes tipos de contenido.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Texto Arrastrable</title> <style> body { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; font-family: Arial, sans-serif; } .zonaDeSoltado { width: 350px; height: 40px; padding: 15px; border: 1px solid #292828; display: flex; align-items: center; justify-content: center; margin-bottom: 20px; } h1 { color: green; margin-bottom: 10px; } p { margin: 0; cursor: grab; } </style> </head> <body> <h1>GeeksforGeeks</h1> <h3>Arrastra el texto al rectángulo</h3> <div class="zonaDeSoltado" ondrop="soltarTexto(event)" ondragover="permitirSoltarOpcion(event)"> </div> <p id="textoArrastrable" draggable="true" ondragstart="iniciarArrastreTexto(event)">GeeksforGeeks: Un portal de ciencia de la computación para geeks.</p> <script> function soltarTexto(evento) { evento.preventDefault(); var datos = evento.dataTransfer.getData("text/plain"); evento.target.appendChild(document.getElementById(datos)); } function permitirSoltarOpcion(evento) { evento.preventDefault(); } function iniciarArrastreTexto(evento) { evento.dataTransfer.setData("text/plain", evento.target.id); } </script> </body> </html>La API de Drag and Drop en HTML5 cuenta con un amplio soporte en los navegadores modernos, incluyendo:
- Google Chrome 4.0+
- Microsoft Edge 9.0+
- Firefox 3.5+
- Opera 6.0+
- Safari 12.0+
Esto garantiza que la funcionalidad Drag and Drop será accesible para la gran mayoría de los usuarios.
¿Qué es un Evento de Drag and Drop en Detalle?
Un evento de Drag and Drop representa una acción específica dentro del proceso de arrastrar y soltar. Como hemos visto, existen varios eventos que se disparan en diferentes momentos de la operación. Para comprender mejor, resumimos los pasos básicos para añadir funcionalidad Drag and Drop a una aplicación y los eventos asociados:
Identificar el Elemento Arrastrable
Como ya hemos mencionado, se utiliza el atributo
draggable="true"para marcar un elemento como arrastrable y se añade un manejador para el eventodragstart.<script> function manejadorDragStart(evento) { // Añadir el ID del elemento arrastrado al objeto dataTransfer evento.dataTransfer.setData("text/plain", evento.target.id); } window.addEventListener("DOMContentLoaded", () => { // Obtener el elemento por su ID const elemento = document.getElementById("parrafoArrastrable"); // Añadir el event listener para el evento dragstart elemento.addEventListener("dragstart", manejadorDragStart); }); </script> <p id="parrafoArrastrable" draggable="true">Este párrafo es arrastrable.</p>Definir los Datos del Arrastre
Podemos incluir múltiples elementos de datos en una operación de arrastre. Cada elemento de datos es una cadena con un tipo específico, generalmente un tipo MIME como
text/html. El objetodataTransfer, accesible desde la propiedaddataTransferde cada eventoDragEvent, gestiona estos datos.
To make an object draggable, set draggable=true on that element. Just about anything can be drag-enabled, including images, files, links, files, or any markup on your page. Here's the CSS for the container and box elements. The only CSS related to the drag feature is the cursor: move property. function manejadorDragStart(evento) { // Añadir diferentes tipos de datos de arrastre evento.dataTransfer.setData("text/plain", evento.target.innerText); evento.dataTransfer.setData("text/html", evento.target.outerHTML); evento.dataTransfer.setData("text/uri-list", evento.target.ownerDocument.location.href); }Definir la Imagen de Arrastre
Por defecto, el navegador proporciona una imagen "fantasma" durante el arrastre. Sin embargo, podemos personalizar esta imagen con el método
setDragImage().// Crear una imagen y usarla como imagen de arrastre. let imagenArrastre = new Image(); imagenArrastre.src = "mi_imagen_arrastre.png"; // Reemplazar con la URL de tu imagen function manejadorDragStart(evento) { evento.dataTransfer.setDragImage(imagenArrastre, 10, 10); // Establecer la imagen y su punto de anclaje }Definir el Efecto de Soltado (dropEffect)
La propiedad
dropEffectcontrola la retroalimentación visual (generalmente el cursor) que se muestra al usuario durante el arrastre. Los valores comunes son:copy(copiar los datos),move(mover los datos), ylink(crear un enlace).function manejadorDragStart(evento) { evento.dataTransfer.dropEffect = "copy"; // Indicar que la operación será una copia }Definir una Zona de Soltado
Para que un elemento sea una zona de soltado, debe escuchar los eventos
dragoverydrop. El eventodragoveres crucial para permitir que el soltado ocurra, y típicamente requiere llamar aevento.preventDefault().<script> function manejadorDragOver(evento) { evento.preventDefault(); // ¡Permitir el soltado! evento.dataTransfer.dropEffect = "move"; // Indicar que se moverá el elemento } function manejadorDrop(evento) { evento.preventDefault(); // Obtener el ID del elemento arrastrado y añadirlo al DOM del destino const datos = evento.dataTransfer.getData("text/plain"); evento.target.appendChild(document.getElementById(datos)); } </script> <p id="zonaSoltado" ondrop="manejadorDrop(event)" ondragover="manejadorDragOver(event)">Zona de Soltado</p>Manejar el Efecto de Soltado en el Evento drop
En el manejador del evento
drop, procesamos los datos arrastrados de la manera deseada. UtilizamosdataTransfer.getData()para recuperar los datos y realizamos las acciones necesarias según la lógica de la aplicación.<script> function manejadorDragStart(evento) { // Añadir el ID del elemento al objeto dataTransfer evento.dataTransfer.setData("application/mi-app", evento.target.id); evento.dataTransfer.effectAllowed = "move"; // Permitir solo la operación 'move' } function manejadorDragOver(evento) { evento.preventDefault(); evento.dataTransfer.dropEffect = "move"; } function manejadorDrop(evento) { evento.preventDefault(); // Obtener el ID del elemento y moverlo al destino const datos = evento.dataTransfer.getData("application/mi-app"); evento.target.appendChild(document.getElementById(datos)); } </script> <p id="elementoArrastrable" draggable="true" ondragstart="manejadorDragStart(event)">Elemento Arrastrable</p> <div id="zonaSoltado" ondrop="manejadorDrop(event)" ondragover="manejadorDragOver(event)">Zona de Soltado</div>Evento dragend: Finalización del Arrastre
El evento
dragendse dispara en el elemento de origen (el elemento que se arrastró) al finalizar la operación de arrastre, independientemente de si fue exitosa o cancelada. Podemos usarlo para realizar acciones de limpieza o restablecimiento de estados.
Haciendo un Elemento Arrastrable en HTML5: Enfoque Alternativo
Además del método básico con el atributo draggable, podemos utilizar JavaScript para hacer elementos arrastrables de forma más dinámica. La API Drag and Drop de HTML5 permite que casi cualquier elemento de la página sea arrastrable. Veamos un enfoque alternativo basado en JavaScript.

Creando Contenido Arrastrable con JavaScript
En la mayoría de los navegadores, el texto seleccionado, las imágenes y los enlaces son arrastrables por defecto. Para otros tipos de contenido, debemos usar la API Drag and Drop. En lugar de draggable="true" en HTML, podemos manipular eventos directamente en JavaScript.
document.addEventListener('DOMContentLoaded', (event) => { function manejadorDragStart(e) { this.style.opacity = '0.4'; // Reducir la opacidad al iniciar el arrastre elementoArrastrado = this; // Guardar referencia al elemento arrastrado e.dataTransfer.effectAllowed = 'move'; // Permitir la operación 'move' e.dataTransfer.setData('text/html', this.innerHTML); // Establecer los datos a arrastrar (HTML) } function manejadorDragEnd(e) { this.style.opacity = '1'; // Restaurar la opacidad al finalizar items.forEach(function (item) { item.classList.remove('over'); // Eliminar clase 'over' de los destinos }); } function manejadorDragOver(e) { if (e.preventDefault) { e.preventDefault(); // Prevenir el comportamiento predeterminado (navegación en enlaces) } return false; } function manejadorDragEnter(e) { this.classList.add('over'); // Añadir clase 'over' al entrar en un destino } function manejadorDragLeave(e) { this.classList.remove('over'); // Eliminar clase 'over' al salir de un destino } function manejadorDrop(e) { e.stopPropagation(); // Detener la propagación del evento if (elementoArrastrado !== this) { elementoArrastrado.innerHTML = this.innerHTML; // Intercambiar contenido HTML this.innerHTML = e.dataTransfer.getData('text/html'); } return false; } let items = document.querySelectorAll('.contenedor .caja'); // Seleccionar elementos arrastrables let elementoArrastrado = null; // Variable para el elemento arrastrado items.forEach(function (item) { item.addEventListener('dragstart', manejadorDragStart); item.addEventListener('dragover', manejadorDragOver); item.addEventListener('dragenter', manejadorDragEnter); item.addEventListener('dragleave', manejadorDragLeave); item.addEventListener('dragend', manejadorDragEnd); item.addEventListener('drop', manejadorDrop); }); });Señales Visuales Adicionales: dragenter, dragover, dragleave
Para mejorar la experiencia del usuario, podemos proporcionar señales visuales durante el arrastre. Los eventos dragenter, dragover y dragleave son útiles para esto. Podemos cambiar el estilo de los posibles destinos de soltado cuando un elemento arrastrable se encuentra sobre ellos.
.caja.over { border: 3px dotted #666; /* Borde punteado para indicar destino */ } En JavaScript, añadimos y removemos la clase over en los manejadores de eventos:
function manejadorDragEnter(e) { this.classList.add('over'); // Añadir clase 'over' al entrar en el destino } function manejadorDragLeave(e) { this.classList.remove('over'); // Eliminar clase 'over' al salir del destino } Finalizando la Función de Soltar (drop) e Intercambio de Contenido
El evento drop es donde se realiza la acción principal al soltar el elemento. En este ejemplo, intercambiamos el contenido HTML entre el elemento de origen y el de destino.
function manejadorDrop(e) { e.stopPropagation(); // Detener la propagación del evento if (elementoArrastrado !== this) { elementoArrastrado.innerHTML = this.innerHTML; // Intercambiar contenido HTML del origen al destino this.innerHTML = e.dataTransfer.getData('text/html'); // Intercambiar contenido HTML del destino al origen } return false; } Propiedades Adicionales de Arrastre: effectAllowed y dropEffect
El objeto dataTransfer ofrece propiedades como effectAllowed y dropEffect para controlar la retroalimentación visual y el tipo de operación de arrastre permitida. effectAllowed restringe el tipo de arrastre permitido (ej: 'move', 'copy'). dropEffect controla el cursor mostrado al usuario sobre el destino (ej: 'copy', 'move', 'link').
Carga de Archivos con Drag and Drop
Drag and Drop es muy útil para permitir a los usuarios cargar archivos directamente desde su escritorio a una aplicación web. La diferencia principal en la implementación para la carga de archivos radica en el manejador del evento drop. En lugar de usar dataTransfer.getData(), accedemos a los archivos a través de la propiedad dataTransfer.files, que contiene un objeto FileList con los archivos arrastrados.
function manejadorDrop(e) { e.stopPropagation(); e.preventDefault(); var archivos = e.dataTransfer.files; // Obtener la lista de archivos arrastrados for (var i = 0, archivo; archivo = archivos[i]; i++) { // Procesar cada archivo en la lista (ej: leer el contenido, subirlo al servidor) console.log("Archivo arrastrado:", archivo.name, archivo.type, archivo.size); } } Preguntas Frecuentes (FAQ) sobre Drag and Drop en HTML5
- ¿Puedo hacer arrastrable cualquier elemento HTML?
- Sí, prácticamente cualquier elemento HTML puede hacerse arrastrable utilizando el atributo
draggable="true"o mediante JavaScript y la API Drag and Drop. - ¿Qué navegadores son compatibles con Drag and Drop en HTML5?
- La funcionalidad Drag and Drop es ampliamente compatible con navegadores modernos como Chrome, Firefox, Edge, Safari y Opera, en versiones relativamente recientes.
- ¿Es necesario usar JavaScript para implementar Drag and Drop?
- Sí, JavaScript es esencial para manejar los eventos de Drag and Drop (
dragstart,dragover,drop, etc.) y definir la lógica de la operación, como la transferencia de datos y las acciones a realizar al soltar. - ¿Cómo puedo personalizar la imagen que se muestra al arrastrar un elemento?
- Puedes utilizar el método
dataTransfer.setDragImage(elemento, x, y)dentro del eventodragstartpara definir una imagen personalizada en lugar de la imagen fantasma por defecto del navegador. - ¿Cómo manejo la carga de archivos mediante Drag and Drop?
- En el evento
drop, accede a la propiedaddataTransfer.filespara obtener un objetoFileListque contiene los archivos arrastrados. Puedes iterar sobre esta lista para procesar cada archivo.
Conclusión
La API de Drag and Drop de HTML5 ofrece una manera poderosa y sencilla de añadir interactividad a tus aplicaciones web. Desde la reordenación de elementos hasta la carga de archivos, esta funcionalidad mejora significativamente la experiencia del usuario, haciendo que las interfaces sean más intuitivas y fáciles de usar. Dominar los eventos clave, el objeto dataTransfer y las técnicas de implementación te permitirá crear experiencias web más atractivas y dinámicas.
