{"id":164051,"date":"2025-05-29T09:00:00","date_gmt":"2025-05-29T07:00:00","guid":{"rendered":"https:\/\/gtechgroup.it\/blog\/drag-and-drop-html5-implementazione\/"},"modified":"2025-05-29T09:00:00","modified_gmt":"2025-05-29T07:00:00","slug":"drag-and-drop-html5-implementazione","status":"publish","type":"post","link":"https:\/\/nuovosito.gtechgroup.it\/blog\/drag-and-drop-html5-implementazione\/","title":{"rendered":"Drag and Drop in HTML5: Guida all&#8217;Implementazione Pratica"},"content":{"rendered":"<p style=\"text-align: justify;\">La funzionalit\u00e0 di <strong>drag and drop<\/strong> (trascina e rilascia) \u00e8 una delle interazioni pi\u00f9 intuitive nelle interfacce grafiche. HTML5 ha standardizzato questa funzionalit\u00e0 con un&#8217;API nativa che permette di implementare il trascinamento di elementi direttamente nel browser, senza la necessit\u00e0 di librerie JavaScript esterne. Dalle liste riordinabili alle aree di caricamento file, il drag and drop arricchisce l&#8217;esperienza utente rendendo le interazioni pi\u00f9 naturali e immediate.<\/p>\n<h2>L&#8217;Attributo draggable<\/h2>\n<p style=\"text-align: justify;\">Il punto di partenza per il drag and drop in HTML5 \u00e8 l&#8217;attributo <strong>draggable<\/strong>. Questo attributo globale, applicabile a qualsiasi elemento HTML, indica se l&#8217;elemento pu\u00f2 essere trascinato dall&#8217;utente. Accetta tre valori: &#8220;true&#8221; per rendere l&#8217;elemento trascinabile, &#8220;false&#8221; per impedirlo e &#8220;auto&#8221; (il valore predefinito) che lascia al browser il comportamento standard.<\/p>\n<p style=\"text-align: justify;\">Per impostazione predefinita, solo le immagini, i link e il testo selezionato sono trascinabili senza alcuna configurazione aggiuntiva. Per rendere trascinabile qualsiasi altro elemento, \u00e8 necessario aggiungere esplicitamente draggable=&#8221;true&#8221; nel markup HTML. \u00c8 importante notare che rendere un elemento trascinabile \u00e8 solo il primo passo: senza i gestori di eventi JavaScript appropriati, il trascinamento non avr\u00e0 alcun effetto pratico.<\/p>\n<p style=\"text-align: justify;\">Dal punto di vista visivo, quando un elemento viene trascinato, il browser crea automaticamente un&#8217;immagine fantasma (ghost image) che segue il cursore. Questa immagine \u00e8 una copia semi-trasparente dell&#8217;elemento originale. \u00c8 possibile personalizzare questa immagine fantasma tramite JavaScript utilizzando il metodo setDragImage() dell&#8217;oggetto DataTransfer, permettendo di mostrare un indicatore visivo personalizzato durante il trascinamento.<\/p>\n<h2>Gli Eventi di Drag and Drop<\/h2>\n<p style=\"text-align: justify;\">L&#8217;API Drag and Drop di HTML5 definisce sette eventi che coprono l&#8217;intero ciclo di vita di un&#8217;operazione di trascinamento. Comprendere quando ciascun evento viene generato e su quale elemento \u00e8 fondamentale per un&#8217;implementazione corretta.<\/p>\n<p style=\"text-align: justify;\">Gli eventi sull&#8217;elemento <strong>trascinato<\/strong> (drag source) sono tre: <strong>dragstart<\/strong> si attiva quando l&#8217;utente inizia a trascinare l&#8217;elemento (il momento in cui si preme il mouse e si inizia a muovere); <strong>drag<\/strong> si attiva continuamente durante il trascinamento, simile a mousemove; e <strong>dragend<\/strong> si attiva quando il trascinamento termina, indipendentemente dal fatto che il rilascio sia avvenuto su una zona valida o meno.<\/p>\n<p style=\"text-align: justify;\">Gli eventi sulla <strong>zona di destinazione<\/strong> (drop target) sono quattro: <strong>dragenter<\/strong> si attiva quando l&#8217;elemento trascinato entra nell&#8217;area della zona di destinazione; <strong>dragover<\/strong> si attiva continuamente mentre l&#8217;elemento \u00e8 sopra la zona di destinazione; <strong>dragleave<\/strong> si attiva quando l&#8217;elemento trascinato esce dalla zona di destinazione; e <strong>drop<\/strong> si attiva quando l&#8217;elemento viene rilasciato sulla zona di destinazione.<\/p>\n<p style=\"text-align: justify;\">Un aspetto cruciale e spesso fonte di confusione: per permettere il rilascio su un elemento, \u00e8 <strong>obbligatorio<\/strong> chiamare event.preventDefault() nel gestore dell&#8217;evento dragover. Il comportamento predefinito del browser, infatti, \u00e8 di rifiutare qualsiasi operazione di drop. Senza preventDefault() nel dragover, l&#8217;evento drop non verr\u00e0 mai generato, indipendentemente dalla configurazione degli altri eventi.<\/p>\n<h2>L&#8217;Oggetto DataTransfer<\/h2>\n<p style=\"text-align: justify;\">L&#8217;oggetto <strong>DataTransfer<\/strong> \u00e8 il cuore del meccanismo di drag and drop, fungendo da contenitore per i dati trasferiti tra la sorgente e la destinazione. \u00c8 accessibile tramite la propriet\u00e0 dataTransfer dell&#8217;evento e fornisce metodi per leggere e scrivere dati durante le diverse fasi del trascinamento.<\/p>\n<p style=\"text-align: justify;\">Il metodo <strong>setData(tipo, dati)<\/strong> viene chiamato nel gestore dragstart per associare dati all&#8217;operazione di trascinamento. Il parametro tipo \u00e8 una stringa che identifica il formato dei dati, tipicamente &#8220;text\/plain&#8221; per testo semplice, &#8220;text\/html&#8221; per markup HTML, o &#8220;text\/uri-list&#8221; per URL. \u00c8 possibile impostare dati in pi\u00f9 formati simultaneamente, permettendo alla zona di destinazione di scegliere il formato pi\u00f9 appropriato.<\/p>\n<p style=\"text-align: justify;\">Il metodo <strong>getData(tipo)<\/strong> viene chiamato nel gestore drop per leggere i dati associati all&#8217;operazione. Per ragioni di sicurezza, getData() \u00e8 accessibile solo nei gestori drop e dragend; negli altri eventi restituisce una stringa vuota. Questa restrizione impedisce a elementi della pagina di &#8220;spiare&#8221; i dati durante il trascinamento.<\/p>\n<p style=\"text-align: justify;\">La propriet\u00e0 <strong>effectAllowed<\/strong>, impostata nel gestore dragstart, indica quali operazioni sono permesse: &#8220;copy&#8221;, &#8220;move&#8221;, &#8220;link&#8221;, &#8220;copyMove&#8221;, &#8220;copyLink&#8221;, &#8220;linkMove&#8221;, &#8220;all&#8221; o &#8220;none&#8221;. La propriet\u00e0 <strong>dropEffect<\/strong>, impostata nel gestore dragover della zona di destinazione, specifica quale operazione verr\u00e0 eseguita al rilascio. Il browser aggiorna l&#8217;icona del cursore in base a queste propriet\u00e0 per dare un feedback visivo all&#8217;utente.<\/p>\n<h2>Esempi Pratici: Lista Riordinabile e Area Upload<\/h2>\n<p style=\"text-align: justify;\">Una <strong>lista riordinabile<\/strong> \u00e8 uno degli esempi pi\u00f9 classici di drag and drop. L&#8217;implementazione prevede di rendere ogni elemento della lista trascinabile, gestire gli eventi per determinare dove l&#8217;elemento viene rilasciato e riordinare il DOM di conseguenza. Nel gestore dragstart, si salva l&#8217;indice dell&#8217;elemento trascinato; nel gestore dragover di ogni elemento della lista, si chiama preventDefault() e si determina se l&#8217;elemento trascinato deve essere inserito prima o dopo l&#8217;elemento corrente; nel gestore drop, si esegue il riordinamento effettivo.<\/p>\n<p style=\"text-align: justify;\">Per migliorare il feedback visivo durante il riordinamento, si possono aggiungere stili CSS tramite i gestori dragenter e dragleave: un bordo colorato o un&#8217;area evidenziata mostra all&#8217;utente dove l&#8217;elemento verr\u00e0 posizionato al rilascio. \u00c8 importante rimuovere gli stili nel gestore dragleave e nel gestore drop per evitare artefatti visivi.<\/p>\n<p style=\"text-align: justify;\">Un&#8217;<strong>area di upload file<\/strong> \u00e8 un altro caso d&#8217;uso molto diffuso. L&#8217;API Drag and Drop permette di trascinare file dal file system direttamente sulla pagina web. I file trascinati sono accessibili tramite la propriet\u00e0 <strong>files<\/strong> dell&#8217;oggetto DataTransfer nel gestore drop. Ogni file \u00e8 un oggetto File con propriet\u00e0 come name, size, type e lastModified, che pu\u00f2 essere inviato al server tramite FormData e Fetch API.<\/p>\n<p style=\"text-align: justify;\">Per l&#8217;area di upload, il pattern tipico prevede di prevenire il comportamento predefinito sia in dragover che in drop (per evitare che il browser apra il file), aggiungere una classe CSS per evidenziare l&#8217;area quando un file viene trascinato sopra di essa, e processare i file al rilascio. Si possono validare i tipi e le dimensioni dei file prima dell&#8217;upload, mostrando messaggi di errore appropriati.<\/p>\n<h2>Stilizzazione degli Stati di Drag<\/h2>\n<p style=\"text-align: justify;\">Una buona implementazione di drag and drop richiede un <strong>feedback visivo<\/strong> chiaro che guidi l&#8217;utente durante l&#8217;interazione. CSS non offre pseudo-classi native per gli stati di drag, quindi la stilizzazione avviene tramite classi JavaScript aggiunte e rimosse nei gestori degli eventi.<\/p>\n<p style=\"text-align: justify;\">Le best practice per la stilizzazione includono: ridurre l&#8217;opacit\u00e0 dell&#8217;elemento sorgente durante il trascinamento per indicare che \u00e8 stato &#8220;sollevato&#8221; (applicando una classe nel gestore dragstart e rimuovendola nel gestore dragend); evidenziare la zona di destinazione quando un elemento vi entra sopra (usando dragenter\/dragleave); mostrare indicatori di posizionamento per le liste riordinabili; e cambiare l&#8217;icona del cursore tramite la propriet\u00e0 dropEffect.<\/p>\n<p style=\"text-align: justify;\">Un problema comune con dragenter e dragleave \u00e8 il fenomeno del &#8220;flickering&#8221;: quando l&#8217;elemento trascinato passa sopra gli elementi figli della zona di destinazione, dragleave viene generato per il genitore prima che dragenter venga generato nuovamente. La soluzione \u00e8 utilizzare un contatore che incrementa su dragenter e decrementa su dragleave, applicando gli stili quando il contatore \u00e8 maggiore di zero.<\/p>\n<h2>Accessibilit\u00e0 del Drag and Drop<\/h2>\n<p style=\"text-align: justify;\">L&#8217;accessibilit\u00e0 \u00e8 l&#8217;aspetto pi\u00f9 critico e spesso trascurato del drag and drop. L&#8217;interazione di trascinamento \u00e8 intrinsecamente basata sul mouse e non \u00e8 accessibile da tastiera senza implementazione aggiuntiva. Le linee guida <strong>WCAG<\/strong> richiedono che ogni funzionalit\u00e0 sia accessibile tramite tastiera.<\/p>\n<p style=\"text-align: justify;\">Per rendere il drag and drop accessibile, \u00e8 necessario fornire un&#8217;alternativa da tastiera. Per le liste riordinabili, pulsanti &#8220;sposta su&#8221; e &#8220;sposta gi\u00f9&#8221; accessibili da tastiera offrono la stessa funzionalit\u00e0. Per le aree di upload, un classico campo input di tipo file \u00e8 il fallback standard. L&#8217;uso di attributi ARIA come aria-grabbed (deprecato ma ancora in uso) e aria-dropeffect fornisce informazioni aggiuntive alle tecnologie assistive.<\/p>\n<p style=\"text-align: justify;\">Le <strong>live regions ARIA<\/strong> (aria-live) possono annunciare i cambiamenti di stato durante il trascinamento, informando gli utenti di screen reader su cosa sta accadendo. Ad esempio, annunciare &#8220;Elemento 3 spostato alla posizione 1&#8221; dopo un riordinamento. Per maggiori dettagli sulle tecniche ARIA, consulta la nostra guida sull&#8217;<a href=\"https:\/\/gtechgroup.it\/blog\/accessibilita-web-html-aria-ruoli\/\">accessibilit\u00e0 web e ARIA<\/a>.<\/p>\n<p style=\"text-align: justify;\">Hai bisogno di aiuto con l&#8217;implementazione del drag and drop nel tuo progetto web? <strong>G Tech Group<\/strong> offre servizi di sviluppo web professionale e consulenza tecnica. Contattaci a <strong>support@gtechgroup.it<\/strong> o via WhatsApp al <strong>0465 84 62 45<\/strong>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>La funzionalit\u00e0 di drag and drop (trascina e rilascia) \u00e8 una delle interazioni pi\u00f9 intuitive nelle interfacce grafiche. HTML5 ha standardizzato questa funzionalit\u00e0 con un&#8217;API&hellip;<\/p>\n","protected":false},"author":2,"featured_media":164231,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1246],"tags":[787],"class_list":["post-164051","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-html","tag-sviluppo-web"],"_links":{"self":[{"href":"https:\/\/nuovosito.gtechgroup.it\/blog\/wp-json\/wp\/v2\/posts\/164051","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nuovosito.gtechgroup.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nuovosito.gtechgroup.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nuovosito.gtechgroup.it\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nuovosito.gtechgroup.it\/blog\/wp-json\/wp\/v2\/comments?post=164051"}],"version-history":[{"count":0,"href":"https:\/\/nuovosito.gtechgroup.it\/blog\/wp-json\/wp\/v2\/posts\/164051\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nuovosito.gtechgroup.it\/blog\/wp-json\/wp\/v2\/media\/164231"}],"wp:attachment":[{"href":"https:\/\/nuovosito.gtechgroup.it\/blog\/wp-json\/wp\/v2\/media?parent=164051"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nuovosito.gtechgroup.it\/blog\/wp-json\/wp\/v2\/categories?post=164051"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nuovosito.gtechgroup.it\/blog\/wp-json\/wp\/v2\/tags?post=164051"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}