W3docs

Attributo HTML draggable

L'attributo HTML draggable è un attributo enumerato che specifica se un elemento è trascinabile o meno. Scopri su quali elementi può essere usato.

L'attributo HTML draggable è un attributo enumerato che specifica se un elemento può essere trascinato dall'utente con un dispositivo di puntamento (mouse o tocco). È il punto di ingresso all'HTML Drag and Drop API, che permette di spostare elementi, testo, file o dati personalizzati da un punto all'altro di una pagina.

Impostare draggable="true" rende semplicemente un elemento selezionabile per il trascinamento. Per spostarlo effettivamente e rilasciarlo in un punto utile, è necessario gestire anche gli eventi di drag and drop e trasportare le informazioni tramite l'object dataTransfer — entrambi trattati di seguito.

Questo attributo può essere usato su qualsiasi elemento HTML. Fa parte degli Attributi globali, quindi funziona insieme ad altri attributi globali come contenteditable.

Valori

L'attributo draggable può assumere i seguenti valori:

  • true — l'elemento può essere trascinato.
  • false — l'elemento non può essere trascinato. Utile per disabilitare il trascinamento predefinito di immagini e link.
  • auto — utilizza il comportamento predefinito del browser per quell'elemento. In pratica ciò significa che immagini e link sono trascinabili, mentre la maggior parte degli altri elementi non lo è. Poiché auto si limita a rimandare al comportamento predefinito, viene raramente scritto esplicitamente; omettere draggable produce lo stesso risultato.
<tag draggable="true|false|auto"></tag>

Nota: draggable non è un attributo boolean. È necessario scrivere il valore esplicitamente — draggable da solo o draggable="" non è valido. Usare sempre draggable="true" o draggable="false".

Come funziona il drag and drop

Un'interazione di drag and drop genera una sequenza di eventi, suddivisi tra l'elemento trascinato (sorgente) e l'elemento su cui viene rilasciato (destinazione):

EventoSi attiva suQuando
dragstartsorgenteL'utente inizia a trascinare l'elemento. Imposta i dati qui con dataTransfer.setData().
dragsorgenteRipetutamente mentre l'elemento viene trascinato.
dragenterdestinazioneL'elemento trascinato entra in un'area di rilascio valida.
dragoverdestinazioneRipetutamente mentre l'elemento si trova sopra un'area di rilascio. Chiamare preventDefault() qui.
dragleavedestinazioneL'elemento trascinato lascia l'area di rilascio.
dropdestinazioneL'elemento viene rilasciato sopra la destinazione. Leggi i dati qui con dataTransfer.getData().
dragendsorgenteIl trascinamento termina (sia che sia stato rilasciato correttamente sia che sia stato annullato).

L'object dataTransfer

Ogni evento di trascinamento espone event.dataTransfer, il canale usato per passare i dati dalla sorgente alla destinazione:

  • event.dataTransfer.setData(format, data) — memorizza una string durante dragstart. Il format è solitamente un tipo MIME come "text/plain" (il codice più vecchio usa "Text", che funziona ancora).
  • event.dataTransfer.getData(format) — legge quella string durante drop.

Poiché i dati diventano disponibili solo al drop, il pattern tipico è memorizzare l'id di un elemento (o qualsiasi identificatore) in dragstart, quindi cercarlo e spostarlo in drop.

Perché preventDefault() è obbligatorio

Per impostazione predefinita, la maggior parte degli elementi non è una destinazione di rilascio valida, quindi il browser annulla il drop. Per fare in modo che un elemento diventi una zona di rilascio è necessario chiamare event.preventDefault() nel suo gestore dragover — questo comunica al browser "sì, il rilascio è consentito qui." È anche comune chiamare preventDefault() nel gestore drop per impedire l'azione predefinita del browser (ad esempio, navigare verso un link trascinato o aprire un file rilasciato).

Se si dimentica preventDefault() in dragover, l'evento drop non si attiva mai e non succede nulla.

Esempio (gestori inline)

Questo esempio usa attributi di gestione eventi inline (ondragstart, ondragover, ondrop). È conciso ma mescola JavaScript nel markup:

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

Esempio (con addEventListener)

Per un codice manutenibile, mantieni il markup pulito e collega i gestori in JavaScript con addEventListener. Questo è l'approccio consigliato:

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

Accessibilità

L'attributo draggable non fornisce alcun supporto per tastiera o screen reader di per sé — il drag and drop è un'interazione esclusivamente tramite puntatore. Gli utenti che navigano con la tastiera o con tecnologie assistive non possono eseguire un trascinamento nativo.

Se il drag and drop è l'unico modo per completare un'azione, offri sempre un'alternativa accessibile (ad esempio, pulsanti "Sposta su / Sposta giù", un menu di selezione o copia/incolla). Tratta il drag and drop nativo come un miglioramento, non come l'unico percorso.

Esercizio

Pratica
Cosa è vero riguardo all'attributo HTML draggable?
Cosa è vero riguardo all'attributo HTML draggable?
Was this page helpful?