Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,91 +8,86 @@ page-type: guide

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](https://github.com/mdn/dom-examples/tree/main/drag-and-drop) (pull requests and/or issues are welcome).

Note that [HTML drag and drop](/en-US/docs/Web/API/HTML_Drag_and_Drop_API) 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).
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.

## 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:
The HTML defines the drop zone as a {{htmlelement("div")}}, and an output region ({{htmlelement("pre")}}) to be populated later.

```html
<div id="drop_zone">
```html live-sample___file-dnd
<div id="drop-zone">
<p>Drag one or more files to this <i>drop zone</i>.</p>
</div>
<pre id="output"></pre>
```

```js
document.getElementById("drop_zone").addEventListener("drop", dropHandler);
As the _target element_, it listens to the {{domxref("HTMLElement/drop_event", "drop")}} event to process the dropped file.

```js live-sample___file-dnd
const dropZone = document.getElementById("drop-zone");
const output = document.getElementById("output");

dropZone.addEventListener("drop", dropHandler);
```

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","dragover")}} event handler:
In order for the `drop` event to fire, the element must also cancel the {{domxref("HTMLElement/dragover_event", "dragover")}} event. Here, we cancel the event on `window` (which would also cancel the event fired on `dropZone` as it bubbles up), because we also want to listen for the `drop` event on `window` to prevent the default browser action of opening the file when it was not dropped into the drop zone.

```js
document
.getElementById("drop_zone")
.addEventListener("dragover", dragOverHandler);
```js live-sample___file-dnd
window.addEventListener("dragover", (e) => {
e.preventDefault();
});
window.addEventListener("drop", (e) => {
e.preventDefault();
});
```

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:

```css
#drop_zone {
```css live-sample___file-dnd
#drop-zone {
border: 5px solid blue;
width: 200px;
height: 100px;
}
```

```css hidden live-sample___file-dnd
div {
margin: 0em;
padding: 2em;
}
```

> [!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](/en-US/docs/Web/API/File_API).
The {{domxref("HTMLElement/drop_event", "drop")}} event is fired when the user drops the file(s). In the following drop handler, the {{domxref("DataTransferItem.getAsFile","getAsFile()")}} method 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](/en-US/docs/Web/API/File_API).

Note that in this example, any drag item that is not a file is ignored.

```js
```js live-sample___file-dnd
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}`);
});
}
let result = "";
// 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();
result += `• file[${i}].name = ${file.name}\n`;
}
});
output.textContent = result;
}
```

## 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.
## Result

```js
function dragOverHandler(ev) {
console.log("File(s) in drop zone");

// Prevent default behavior (Prevent file from being opened)
ev.preventDefault();
}
```
{{EmbedLiveSample("file-dnd", "", 300)}}

## See also

Expand Down