W3docs

Atributo draggable de HTML

El atributo draggable de HTML especifica si un elemento puede ser arrastrado por el usuario. Descubre sus valores y cómo funciona la API de arrastre.

El atributo draggable de HTML es un atributo enumerado que especifica si un elemento puede ser arrastrado por el usuario con un dispositivo señalador (ratón o táctil). Es el punto de entrada a la HTML Drag and Drop API, que permite mover elementos, texto, archivos o datos personalizados de un lugar a otro dentro de una página.

Establecer draggable="true" solo hace que el elemento sea seleccionable. Para mover algo y soltarlo en un lugar útil, también es necesario manejar los eventos de arrastrar y soltar y transmitir información a través del objeto dataTransfer — ambos aspectos se explican a continuación.

Puedes usar este atributo en cualquier elemento HTML. Forma parte de los Atributos Globales, por lo que funciona junto a otros atributos globales como contenteditable.

Valores

El atributo draggable puede tener los siguientes valores:

  • true — el elemento puede ser arrastrado.
  • false — el elemento no puede ser arrastrado. Útil para deshabilitar el arrastre predeterminado de imágenes y enlaces.
  • auto — usa el comportamiento predeterminado del navegador para ese elemento. En la práctica, esto significa que las imágenes y los enlaces son arrastrables, y la mayoría de los demás elementos no lo son. Como auto simplemente aplaza el comportamiento predeterminado, rara vez se escribe de forma explícita; omitir draggable produce el mismo resultado.
<tag draggable="true|false|auto"></tag>

Nota: draggable no es un atributo boolean. Debes escribir el valor de forma explícita — draggable solo o draggable="" no es válido. Usa siempre draggable="true" o draggable="false".

Cómo funciona el arrastrar y soltar

Una interacción de arrastrar y soltar dispara una secuencia de eventos, divididos entre el elemento que se arrastra (la fuente) y el elemento sobre el que se suelta (el destino):

EventoSe dispara enCuándo
dragstartfuenteEl usuario comienza a arrastrar el elemento. Establece tus datos aquí con dataTransfer.setData().
dragfuenteRepetidamente mientras el elemento está siendo arrastrado.
dragenterdestinoEl elemento arrastrado entra en un destino de colocación válido.
dragoverdestinoRepetidamente mientras el elemento está sobre un destino de colocación. Llama a preventDefault() aquí.
dragleavedestinoEl elemento arrastrado abandona el destino de colocación.
dropdestinoEl elemento se suelta sobre el destino. Lee tus datos aquí con dataTransfer.getData().
dragendfuenteEl arrastre termina (tanto si se soltó correctamente como si se canceló).

El objeto dataTransfer

Cada evento de arrastre expone event.dataTransfer, el canal utilizado para pasar datos de la fuente al destino:

  • event.dataTransfer.setData(format, data) — almacena un string durante dragstart. El format suele ser un tipo MIME como "text/plain" (el código antiguo usa "Text", que sigue funcionando).
  • event.dataTransfer.getData(format) — lee ese string durante drop.

Dado que los datos solo están disponibles en drop, el patrón habitual es almacenar el id de un elemento (o cualquier identificador) en dragstart y luego buscarlo y moverlo en drop.

Por qué preventDefault() es obligatorio

Por defecto, la mayoría de los elementos no son destinos de colocación válidos, por lo que el navegador cancela la operación. Para hacer que un elemento actúe como zona de colocación, debes llamar a event.preventDefault() en su manejador dragover — esto le indica al navegador "sí, aquí se permite soltar". También es habitual llamar a preventDefault() en el manejador drop para detener la acción predeterminada del navegador (por ejemplo, navegar a un enlace arrastrado o abrir un archivo soltado).

Si olvidas preventDefault() en dragover, el evento drop nunca se dispara y no ocurre nada.

Ejemplo (manejadores en línea)

Este ejemplo usa atributos de manejadores de eventos en línea (ondragstart, ondragover, ondrop). Es conciso, pero mezcla JavaScript en el marcado:

<!DOCTYPE HTML>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      #rectId {
        width: 350px;
        height: 70px;
        padding: 10px;
        border: 1px solid #aaaaaa;
      }
    </style>
    <script>
      function allowDrop(event) {
        event.preventDefault(); // Allow dropping
      }
      function drag(event) {
        // Store the dragged element's ID in the dataTransfer object
        event.dataTransfer.setData("text/plain", event.target.id);
      }
      function drop(event) {
        event.preventDefault();
        var data = event.dataTransfer.getData("text/plain"); // Retrieve the ID
        event.target.appendChild(document.getElementById(data));
      }
    </script>
  </head>
  <body>
    <div id="rectId" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <br />
    <p id="dragId" draggable="true" ondragstart="drag(event)">
      This is a draggable paragraph. Drag this item to the rectangle.
    </p>
  </body>
</html>

Ejemplo (con addEventListener moderno)

Para un código mantenible, mantén el marcado limpio y adjunta los manejadores en JavaScript con addEventListener. Este es el enfoque recomendado:

<!DOCTYPE HTML>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      #dropzone {
        width: 350px;
        height: 70px;
        padding: 10px;
        border: 1px solid #aaaaaa;
      }
    </style>
  </head>
  <body>
    <div id="dropzone"></div>
    <br />
    <p id="item" draggable="true">
      This is a draggable paragraph. Drag this item to the rectangle.
    </p>

    <script>
      const item = document.getElementById("item");
      const dropzone = document.getElementById("dropzone");

      // Source: store the dragged element's ID when the drag begins.
      item.addEventListener("dragstart", (event) => {
        event.dataTransfer.setData("text/plain", event.target.id);
      });

      // Target: allow dropping by preventing the default handling.
      dropzone.addEventListener("dragover", (event) => {
        event.preventDefault();
      });

      // Target: move the element into the drop zone.
      dropzone.addEventListener("drop", (event) => {
        event.preventDefault();
        const id = event.dataTransfer.getData("text/plain");
        const dragged = document.getElementById(id);
        event.currentTarget.appendChild(dragged);
      });
    </script>
  </body>
</html>

Accesibilidad

El atributo draggable no ofrece soporte para teclado ni para lectores de pantalla por sí solo — arrastrar y soltar es una interacción exclusiva del puntero. Los usuarios que navegan con teclado o tecnología de asistencia no pueden realizar un arrastre nativo.

Si arrastrar y soltar es la única forma de completar una acción, ofrece siempre una alternativa accesible (por ejemplo, botones de "Subir / Bajar", un menú de selección o copiar/pegar). Trata el arrastrar y soltar nativo como una mejora, no como la única vía.

Práctica

Práctica
¿Qué es verdad sobre el atributo draggable de HTML?
¿Qué es verdad sobre el atributo draggable de HTML?
Was this page helpful?