The HTML5 Drag and Drop API  |  Articles  |  web.dev (2024)

This post explains the basics of drag and drop.

Create draggable content

In most browsers, text selections, images, and links are draggable by default.For example, if you drag a link on a web page you'ill see a small box with atitle and URL that you can drop on the address bar or the desktop to create ashortcut or navigate to the link. To make other types of content draggable, youneed to use the HTML5 Drag and Drop APIs.

To make an object draggable, set draggable=true on that element. Just aboutanything can be drag-enabled, including images, files, links, files, or anymarkup on your page.

The following example creates an interface to rearrange columns that have beenlaid out with CSS Grid. The basic markup for the columns looks like this, with the draggable attribute for each column set to true:

<div class="container"> <div draggable="true" class="box">A</div> <div draggable="true" class="box">B</div> <div draggable="true" class="box">C</div></div>

Here's the CSS for the container and box elements. The only CSS related to thedrag feature is the cursor: moveproperty. The rest of the code controls the layout and styling of the containerand box elements.

.container { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px;}.box { border: 3px solid #666; background-color: #ddd; border-radius: .5em; padding: 10px; cursor: move;}

At this point you can drag the items, but nothing else happens. To addbehavior, you need to use the JavaScript API.

Listen for dragging events

To monitor the drag process, you can listen for any of the following events:

To handle the drag flow, you need some kind of source element (where the dragstarts), the data payload (the thing being dragged), and a target (an area tocatch the drop). The source element can be almost any kind of element. Thetarget is the drop zone or set of drop zones that accepts the data the user istrying to drop. Not all elements can be targets. For example, your target can'tbe an image.

Start and end a drag sequence

After you define draggable="true" attributes on your content, attach adragstart event handler to start the drag sequence for each column.

This code sets the column's opacity to 40% when the user starts dragging it,then return it to 100% when the dragging event ends.

function handleDragStart(e) { this.style.opacity = '0.4';}function handleDragEnd(e) { this.style.opacity = '1';}let items = document.querySelectorAll('.container .box');items.forEach(function (item) { item.addEventListener('dragstart', handleDragStart); item.addEventListener('dragend', handleDragEnd);});

The result can be seen in the following Glitch demo. Drag an item, and itsopacity changes. Because the source element has the dragstart event, settingthis.style.opacity to 40% gives the user visual feedback that that element isthe current selection being moved. When you drop the item, the source elementreturns to 100% opacity, even though you haven't defined the drop behavior yet.

Add additional visual cues

To help the user understand how to interact with your interface, use thedragenter, dragover and dragleave event handlers. In this example, thecolumns are drop targets in addition to being draggable. Help the user tounderstand this by making the border dashed when they hold a dragged item over acolumn. For example, in your CSS, you might create an over class forelements that are drop targets:

.box.over { border: 3px dotted #666;}

Then, in your JavaScript, set up the event handlers, add the over class whenthe column is dragged over, and remove it when the dragged element leaves. Inthe dragend handler we also make sure to remove the classes at the end of thedrag.

document.addEventListener('DOMContentLoaded', (event) => { function handleDragStart(e) { this.style.opacity = '0.4'; } function handleDragEnd(e) { this.style.opacity = '1'; items.forEach(function (item) { item.classList.remove('over'); }); } function handleDragOver(e) { e.preventDefault(); return false; } function handleDragEnter(e) { this.classList.add('over'); } function handleDragLeave(e) { this.classList.remove('over'); } let items = document.querySelectorAll('.container .box'); items.forEach(function(item) { item.addEventListener('dragstart', handleDragStart); item.addEventListener('dragover', handleDragOver); item.addEventListener('dragenter', handleDragEnter); item.addEventListener('dragleave', handleDragLeave); item.addEventListener('dragend', handleDragEnd); item.addEventListener('drop', handleDrop); });});

There are a couple of points worth covering in this code:

  • The default actionfor dragover event is to set the dataTransfer.dropEffect property to"none". The dropEffect property is covered later on this page. For now,just know that it prevents the drop event from firing. To override thisbehavior, call e.preventDefault(). Another good practice is to returnfalse in that same handler.

  • The dragenter event handler is used to toggle the over class instead ofdragover. If you use dragover, the event fires repeatedly while the userholds the dragged item over a column, causing the CSS class to togglerepeatedly. This makes the browser do a lot of unnecessary rendering work,which can affect the user experience. We strongly recommend minimizingredraws, and if you need to use dragover, considerthrottling or debouncing your event listener.

Complete the drop

To process the drop, add an event listener for the drop event. In the drophandler, you'll need to prevent the browser's default behavior for drops, whichis typically some sort of annoying redirect. To do this, call e.stopPropagation().

function handleDrop(e) { e.stopPropagation(); // stops the browser from redirecting. return false;}

Be sure to register the new handler alongside the other handlers:

 let items = document.querySelectorAll('.container .box'); items.forEach(function(item) { item.addEventListener('dragstart', handleDragStart); item.addEventListener('dragover', handleDragOver); item.addEventListener('dragenter', handleDragEnter); item.addEventListener('dragleave', handleDragLeave); item.addEventListener('dragend', handleDragEnd); item.addEventListener('drop', handleDrop); });

If you run the code at this point, the item doesn't drop to the new location. Tomake that happen, use the DataTransferobject.

The dataTransfer property holds the data sent in a drag action. dataTransferis set in the dragstart event and read or handled in the drop event. Callinge.dataTransfer.setData(mimeType, dataPayload) lets you set the object's MIMEtype and data payload.

In this example, we're going to let users rearrange the order of the columns.To do that, first you need to store the source element's HTML when the dragstarts:

function handleDragStart(e) { this.style.opacity = '0.4'; dragSrcEl = this; e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/html', this.innerHTML);}

In the drop event, you process the column drop by setting the source column'sHTML to the HTML of the target column that you dropped the data on. Thisincludes checking that the user isn't dropping back onto the same column theydragged from.

function handleDrop(e) { e.stopPropagation(); if (dragSrcEl !== this) { dragSrcEl.innerHTML = this.innerHTML; this.innerHTML = e.dataTransfer.getData('text/html'); } return false;}

You can see the result in the following demo. For this to work, you'll need adesktop browser. The Drag and Drop API isn't supported on mobile. Drag andrelease the A column on top of the B column and notice how they change places:

More dragging properties

The dataTransfer object exposes properties to provide visual feedback to theuser during the drag process and control how each drop target responds to aparticular data type.

  • dataTransfer.effectAllowedrestricts what 'type of drag' the user can perform on the element. It's usedin the drag-and-drop processing model to initialize the dropEffect duringthe dragenter and dragover events. The property can have thefollowing values: none, copy, copyLink, copyMove, link, linkMove,move, all, and uninitialized.
  • dataTransfer.dropEffectcontrols the feedback that the user gets during the dragenter and dragoverevents. When the user holds their pointer over a target element, the browser'scursor indicates what type of operation is going to take place, such as a copyor a move. The effect can take one of the following values: none, copy,link, move.
  • e.dataTransfer.setDragImage(imgElement, x, y)means that instead of using the browser's default 'ghost image' feedback, youcan set a drag icon.

File upload

This simple example uses a column as both the drag source and drag target. Thismight happen in a UI that asks the user to rearrange items. In some situations,the drag target and source might be different element types, as in an interfacewhere the user needs to select one image as the main image for a product bydragging the selected image onto a target.

Drag and Drop is frequently used to let users drag items from their desktop intoan application. The main difference is in your drop handler. Instead of usingdataTransfer.getData() to access the files, their data is contained in thedataTransfer.files property:

function handleDrop(e) { e.stopPropagation(); // Stops some browsers from redirecting. e.preventDefault(); var files = e.dataTransfer.files; for (var i = 0, f; (f = files[i]); i++) { // Read the File objects in this FileList. }}

You can find more information about this inCustom drag-and-drop.

More resources

The HTML5 Drag and Drop API  |  Articles  |  web.dev (2024)
Top Articles
2024 Tax Guide: When to DIY & When to Hire a Tax Professional
World Report 2024: Rights Trends in North Korea
Srtc Tifton Ga
Craigslist Home Health Care Jobs
Places 5 Hours Away From Me
My E Chart Elliot
Paris 2024: Kellie Harrington has 'no more mountains' as double Olympic champion retires
Craigslist Mpls Mn Apartments
Rabbits Foot Osrs
Geodis Logistic Joliet/Topco
How to Watch Braves vs. Dodgers: TV Channel & Live Stream - September 15
Campaign Homecoming Queen Posters
Miami Valley Hospital Central Scheduling
Costco Gas Foster City
Paychex Pricing And Fees (2024 Guide)
Florida History: Jacksonville's role in the silent film industry
SF bay area cars & trucks "chevrolet 50" - craigslist
97226 Zip Code
Johnnie Walker Double Black Costco
Dcf Training Number
Dragonvale Valor Dragon
‘The Boogeyman’ Review: A Minor But Effectively Nerve-Jangling Stephen King Adaptation
Certain Red Dye Nyt Crossword
Walgreens 8 Mile Dequindre
Living Shard Calamity
Olivia Maeday
2021 MTV Video Music Awards: See the Complete List of Nominees - E! Online
Egusd Lunch Menu
Dal Tadka Recipe - Punjabi Dhaba Style
Askhistorians Book List
10 Best Quotes From Venom (2018)
Transformers Movie Wiki
47 Orchid Varieties: Different Types of Orchids (With Pictures)
Martin Village Stm 16 & Imax
De beste uitvaartdiensten die goede rituele diensten aanbieden voor de laatste rituelen
Www Violationinfo Com Login New Orleans
The Bold And The Beautiful Recaps Soap Central
Oxford Alabama Craigslist
Ludvigsen Mortuary Fremont Nebraska
Skip The Games Grand Rapids Mi
Qlima© Petroleumofen Elektronischer Laserofen SRE 9046 TC mit 4,7 KW CO2 Wächter • EUR 425,95
Busted Newspaper Campbell County KY Arrests
Suffix With Pent Crossword Clue
11526 Lake Ave Cleveland Oh 44102
The Wait Odotus 2021 Watch Online Free
Lucyave Boutique Reviews
Greg Steube Height
Bf273-11K-Cl
Nfsd Web Portal
Psalm 46 New International Version
Latest Posts
Article information

Author: Eusebia Nader

Last Updated:

Views: 6643

Rating: 5 / 5 (60 voted)

Reviews: 83% of readers found this page helpful

Author information

Name: Eusebia Nader

Birthday: 1994-11-11

Address: Apt. 721 977 Ebert Meadows, Jereville, GA 73618-6603

Phone: +2316203969400

Job: International Farming Consultant

Hobby: Reading, Photography, Shooting, Singing, Magic, Kayaking, Mushroom hunting

Introduction: My name is Eusebia Nader, I am a encouraging, brainy, lively, nice, famous, healthy, clever person who loves writing and wants to share my knowledge and understanding with you.