File drag and drop
{{DefaultAPISidebar("HTML Drag and Drop API")}}
HTML Drag and Drop interfaces enable web applications to drag and drop files on a web page. This document describes how an application can accept one or more files that are dragged from the underlying platform’s file manager and dropped on a web page.
The main steps to drag and drop are to define a drop zone (i.e. a target element for the file drop) and to define event handlers for the {{domxref("HTMLElement/drop_event", "drop")}}
and {{domxref("HTMLElement/dragover_event", "dragover")}}
events. These steps are described below, including example code snippets. The full source code is available in MDN’s drag-and-drop repository (pull requests and/or issues are welcome).
Note that HTML drag and drop defines two different APIs to support dragging and dropping files. One API is the {{domxref("DataTransfer")}}
interface and the second API is the {{domxref("DataTransferItem")}}
and {{domxref("DataTransferItemList")}}
interfaces. This example illustrates the use of both APIs (and does not use any Gecko specific interfaces).
Define the drop zone
The target element of the {{domxref("HTMLElement/drop_event", "drop")}}
event needs an ondrop
event handler. The following code snippet shows how this is done with a {{HTMLelement("div")}}
element:
<div id="drop_zone" ondrop="dropHandler(event);">
<p>Drag one or more files to this <i>drop zone</i>.</p>
</div>
Typically, an application will include a {{domxref("HTMLElement/dragover_event", "dragover")}}
event handler on the drop target element and that handler will turn off the browser’s default drag behavior. To add this handler, you need to include a {{domxref("HTMLElement.dragover_event","ondragover")}}
event handler:
<div
id="drop_zone"
ondrop="dropHandler(event);"
ondragover="dragOverHandler(event);">
<p>Drag one or more files to this <i>drop zone</i>.</p>
</div>
Lastly, an application may want to style the drop target element to visually indicate the element is a drop zone. In this example, the drop target element uses the following styling:
#drop_zone {
border: 5px solid blue;
width: 200px;
height: 100px;
}
Note:
{{domxref("HTMLElement/dragstart_event", "dragstart")}}
and{{domxref("HTMLElement/dragend_event", "dragend")}}
events are not fired when dragging a file into the browser from the OS. To detect when OS files are dragged into the browser, use{{domxref("HTMLElement/dragenter_event", "dragenter")}}
and{{domxref("HTMLElement/dragleave_event", "dragleave")}}
. This means that it is not possible to use{{domxref("DataTransfer.setDragImage","setDragImage()")}}
to apply a custom drag image/cursor overlay when dragging files from the OS — because the drag data store can only be modified in the{{domxref("HTMLElement/dragstart_event", "dragstart")}}
event. This also applies to{{domxref("DataTransfer.setData","setData()")}}
.
Process the drop
The {{domxref("HTMLElement/drop_event", "drop")}}
event is fired when the user drops the file(s). In the following drop handler, if the browser supports {{domxref("DataTransferItemList")}}
interface, the {{domxref("DataTransferItem.getAsFile","getAsFile()")}}
method is used to access each file; otherwise the {{domxref("DataTransfer")}}
interface’s {{domxref("DataTransfer.files","files")}}
property is used to access each file.
This example shows how to write the name of each dragged file to the console. In a real application, an application may want to process a file using the File API.
Note that in this example, any drag item that is not a file is ignored.
function dropHandler(ev) {
console.log("File(s) dropped");
// Prevent default behavior (Prevent file from being opened)
ev.preventDefault();
if (ev.dataTransfer.items) {
// Use DataTransferItemList interface to access the file(s)
[...ev.dataTransfer.items].forEach((item, i) => {
// If dropped items aren't files, reject them
if (item.kind === "file") {
const file = item.getAsFile();
console.log(`… file[${i}].name = ${file.name}`);
}
});
} else {
// Use DataTransfer interface to access the file(s)
[...ev.dataTransfer.files].forEach((file, i) => {
console.log(`… file[${i}].name = ${file.name}`);
});
}
}
Prevent the browser’s default drag behavior
The following {{domxref("HTMLElement/dragover_event", "dragover")}}
event handler calls {{domxref("Event.preventDefault","preventDefault()")}}
to turn off the browser’s default drag and drop handler.
function dragOverHandler(ev) {
console.log("File(s) in drop zone");
// Prevent default behavior (Prevent file from being opened)
ev.preventDefault();
}