W3docs

Атрибут 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 как улучшение, а не единственный сценарий.

Практика

Практика
Что верно об атрибуте HTML draggable?
Что верно об атрибуте HTML draggable?
Was this page helpful?