Атрибут HTML draggable
Атрибут HTML draggable — перечисляемый атрибут, указывающий, можно ли перетаскивать элемент. Узнайте, на каких элементах он применяется.
Атрибут HTML draggable — это перечисляемый атрибут, который указывает, может ли пользователь перетащить элемент с помощью указывающего устройства (мыши или касания). Он является точкой входа в HTML Drag and Drop API, позволяющий перемещать элементы, текст, файлы или произвольные данные из одного места на странице в другое.
Установка draggable="true" лишь делает элемент доступным для захвата. Чтобы реально что-то переместить и поместить в нужное место, необходимо также обрабатывать события перетаскивания и передавать данные через объект dataTransfer — оба аспекта рассмотрены ниже.
Атрибут можно использовать на любом HTML-элементе. Он входит в состав глобальных атрибутов и работает совместно с другими глобальными атрибутами, например contenteditable.
Значения
Атрибут draggable может принимать следующие значения:
true— элемент можно перетаскивать.false— элемент нельзя перетаскивать. Полезно для отключения стандартного перетаскивания изображений и ссылок.auto— используется поведение браузера по умолчанию для данного элемента. На практике это означает, что изображения и ссылки перетаскиваются, а большинство других элементов — нет. Посколькуautoпросто делегирует управление поведению по умолчанию, это значение редко указывают явно; пропуск атрибутаdraggableдаёт тот же результат.
<tag draggable="true|false|auto"></tag>Примечание:
draggable— не boolean-атрибут. Значение необходимо указывать явно —draggableбез значения илиdraggable=""недопустимо. Всегда используйтеdraggable="true"илиdraggable="false".
Как работает перетаскивание
Взаимодействие drag-and-drop запускает последовательность событий, разделённых между перетаскиваемым элементом (источником) и элементом, на который его бросают (целью):
| Событие | Срабатывает на | Когда |
|---|---|---|
dragstart | источник | Пользователь начинает перетаскивать элемент. Здесь задавайте данные через dataTransfer.setData(). |
drag | источник | Многократно, пока элемент перетаскивается. |
dragenter | цель | Перетаскиваемый элемент входит в допустимую зону сброса. |
dragover | цель | Многократно, пока элемент находится над зоной сброса. Вызовите здесь preventDefault(). |
dragleave | цель | Перетаскиваемый элемент покидает зону сброса. |
drop | цель | Элемент отпускается над целью. Считывайте данные здесь через dataTransfer.getData(). |
dragend | источник | Перетаскивание завершено (независимо от того, был ли сброс успешным или отменён). |
Объект dataTransfer
Каждое событие перетаскивания предоставляет event.dataTransfer — канал для передачи данных от источника к цели:
event.dataTransfer.setData(format, data)— сохраняет строку во времяdragstart. В качествеformatобычно используется MIME-тип, например"text/plain"(в старом коде используется"Text", что по-прежнему работает).event.dataTransfer.getData(format)— считывает сохранённую строку во времяdrop.
Поскольку данные становятся доступны только при drop, типичный подход — сохранить id элемента (или любой идентификатор) в dragstart, а затем найти его и переместить в drop.
Почему необходим preventDefault()
По умолчанию большинство элементов не являются допустимыми зонами сброса, поэтому браузер отменяет drop. Чтобы сделать элемент зоной сброса, нужно вызвать event.preventDefault() в обработчике dragover — это сообщает браузеру: «да, сброс здесь разрешён». Также принято вызывать preventDefault() в обработчике drop, чтобы отменить стандартное действие браузера (например, переход по перетащенной ссылке или открытие брошенного файла).
Если забыть вызвать preventDefault() в dragover, событие drop никогда не произойдёт и ничего не случится.
Пример (встроенные обработчики)
В этом примере используются встроенные атрибуты обработчиков событий (ondragstart, ondragover, ondrop). Код лаконичен, но смешивает JavaScript с разметкой:
<!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>Пример (современный addEventListener)
Для поддерживаемого кода оставляйте разметку чистой и подключайте обработчики через JavaScript с помощью addEventListener. Это рекомендуемый подход:
<!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>Доступность
Атрибут draggable не обеспечивает поддержку клавиатуры или программ чтения с экрана — перетаскивание является взаимодействием только с помощью указателя. Пользователи, работающие с клавиатурой или вспомогательными технологиями, не могут выполнить нативное перетаскивание.
Если перетаскивание — единственный способ выполнить действие, всегда предоставляйте доступную альтернативу (например, кнопки «Переместить вверх / Переместить вниз», выпадающий список или копирование/вставка). Рассматривайте нативное drag-and-drop как улучшение, а не единственный сценарий.