Гид по технологиям

Перетаскивание (Drag and Drop) в браузере: практическое руководство

6 min read Веб-разработка Обновлено 19 Dec 2025
Drag and Drop в браузере — практическое руководство
Drag and Drop в браузере — практическое руководство

Разработчик за компьютером работает с кодом и интерфейсами

Основы drag and drop в HTML

Перетаскивание в браузере обычно разделяет элементы на два типа:

  • Перетаскиваемые элементы (draggable) — те, которые пользователь может схватить и переместить.
  • Зоны приёма (drop targets) — те, куда можно положить перетаскиваемый элемент.

Чтобы сделать элемент перетаскиваемым, добавьте атрибут draggable=”true”:

Этот элемент можно перетаскивать

Когда пользователь начинает перетаскивание, браузер по умолчанию отображает “призрачное” изображение (ghost image), дающее визуальную обратную связь.

По умолчанию браузер показывает «призрачное» изображение при перетаскивании

Вы можете заменить это изображение своим, используя event.dataTransfer.setDragImage. Пример:

let img = new Image();
img.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Twemoji_1f600.svg/220px-Twemoji_1f600.svg.png';

document.querySelector('div').addEventListener('dragstart', (event) => {
  event.dataTransfer.setDragImage(img, 10, 10);
});

Первый параметр — элемент изображения, два последующих — горизонтальный и вертикальный сдвиг в пикселях.

Пользовательское изображение, отображаемое при перетаскивании элемента

Чтобы позволить бросок в зоне приёма, надо отменить поведение по умолчанию для событий dragenter и dragover:

const dropElement = document.querySelector('.drop-target');

dropElement.addEventListener('dragenter', (ev) => {
  ev.preventDefault();
});

dropElement.addEventListener('dragover', (ev) => {
  ev.preventDefault();
});

Важно: элемент-зона приёма должен корректно обрабатывать эти события, иначе браузер не позволит выполнить drop.

Интерфейс DragEvent и список событий

JavaScript предоставляет интерфейс DragEvent, в котором определены следующие события:

  • drag — генерируется, пока элемент находится в состоянии перетаскивания.
  • dragstart — начало операции перетаскивания.
  • dragend — окончание операции перетаскивания (при отпускании или прерывании).
  • dragenter — перетаскиваемый элемент вошёл в зону приёма.
  • dragleave — элемент покинул зону приёма.
  • dragover — элемент находится над зоной приёма (обычно нужно preventDefault).
  • drop — пользователь бросает элемент в зону приёма.

Обратите внимание: при перетаскивании файлов из файловой системы браузер не вызывает события dragstart/dragend на элементах страницы — источник событий другой. Это поведение влияет на тестирование и обработку событий.

Программная генерация DragEvent

Иногда полезно инициировать drag-события программно, например для демонстрации или тестов:

const customDragStartEvent = new DragEvent('dragstart', {
  dataTransfer: new DataTransfer(),
});

const customDragEndEvent = new DragEvent('dragend');

const draggableElement = document.querySelector('#draggable');

draggableElement.addEventListener('dragstart', (event) => {
  console.log('Drag started!');
  event.dataTransfer.setData('text/plain', 'Hello, world!');
});

draggableElement.addEventListener('dragend', () => {
  console.log('Drag ended!');
});

// Запуск событий вручную
// draggableElement.dispatchEvent(customDragStartEvent);
// draggableElement.dispatchEvent(customDragEndEvent);

Передача данных через dataTransfer

Объект dataTransfer служит как временное хранилище между источником и целью перетаскивания. Через него можно передать текст, URL, бинарные данные (файлы) и нестандартные MIME-типы.

Упаковка данных с помощью setData()

element.addEventListener('dragstart', (event) => {
  event.dataTransfer.setData('text/plain', 'Hello, world!');
});

Вы указываете тип данных и значение. Типы важно согласовать на стороне приёма.

Получение данных с помощью getData()

element.addEventListener('drop', (event) => {
  const transferredData = event.dataTransfer.getData('text/plain');
  console.log(`Получены данные: ${transferredData}`);
});

Для передачи файлов используйте event.dataTransfer.files — это FileList.

Когда использовать drag and drop: кейсы

  • Загрузчики файлов: перетаскивание упрощает добавление файлов для пользователей.
  • Сортируемые списки: таск-менеджеры, плейлисты, галереи — удобная интерактивность.
  • Настраиваемые панели: пользователи могут переставлять виджеты на дашборде.

Однако не всегда стоит внедрять drag and drop: если задача часто выполняется с клавиатуры или для пользователей с ограниченными возможностями, подумайте о дополнительных способах взаимодействия.

Доступность и альтернативы управления

Перетаскивание часто недоступно по умолчанию для пользователей клавиатуры и вспомогательных технологий. Рекомендации:

  • Реализуйте клавиатурные операции: выбрать элемент — стрелками переместить — подтвердить положение (Enter или Space).
  • Добавьте aria-grabbed, role=”list”/“listitem” и aria-dropeffect там, где уместно.
  • Обеспечьте видимую фокусную рамку и текстовые подсказки (например, “Нажмите пробел, чтобы начать перемещение”).
  • Используйте live-region для объявлений при изменении порядка.
  • Предоставьте альтернативную форму ввода (вставка URL, кнопка “Загрузить файл”).

Пример простой клавиатурной поддержки:

// упрощённый пример: управление фокусом и перетаскиванием с клавиатуры
element.addEventListener('keydown', (e) => {
  if (e.code === 'Space') {
    // начать/закончить режим перемещения
    e.preventDefault();
    element.classList.toggle('dragging-by-keyboard');
  }
  if (element.classList.contains('dragging-by-keyboard')) {
    if (e.code === 'ArrowUp') moveElementUp(element);
    if (e.code === 'ArrowDown') moveElementDown(element);
  }
});

Паттерн реализации: пошаговая методология

  1. Проектирование UX: решите, зачем нужен drag and drop и какие альтернативы предоставить.
  2. Прототип: реализуйте базовые события dragstart/dragover/drop и визуальную подсказку.
  3. Передача данных: согласуйте MIME-типы и структуру dataTransfer.
  4. Доступность: добавьте клавиатуру, aria-атрибуты и сообщения для вспомогательных технологий.
  5. Тестирование: кроссбраузерное и на устройствах с тач-управлением.
  6. Безопасность: проверяйте загружаемые файлы и лимиты.
  7. Мониторинг: логируйте ошибки и поведение пользователей.

Практическое руководство для команды (SOP)

Role-based checklist:

  • Разработчик:

    • Реализовать dragstart/dragend, dragover с preventDefault и drop.
    • Передавать минимально необходимую информацию через dataTransfer.
    • Обрабатывать файлы через event.dataTransfer.files и кешировать в безопасном месте.
  • UX/UI дизайнер:

    • Предусмотреть состояния: нормальное, перетаскивается, потенциальная зона приёма, ошибка.
    • Подумать о текстовых подсказках и иконках для мобильных.
  • QA инженер:

    • Тесты на порядок элементов, перенос файлов, граничные размеры файлов и разных типов.
    • Тесты клавиатуры и screen reader.
  • Продукт-менеджер:

    • Решить критерии приёмки и приоритетные сценарии.

Критерии приёмки

  • Элемент можно перетаскивать мышью и завершать операцию drop в назначенной зоне.
  • Данные корректно передаются через dataTransfer между элементами.
  • Пользователь может выполнить ту же операцию с клавиатуры (или получить альтернативу).
  • Ограничения по размерам и типам файлов соблюдаются и пользователь получает понятную ошибку.

Тесты и сценарии приёмки

  1. Drag & drop простого текстового элемента: текст передаётся и отображается в целевом элементе.
  2. Drag & drop файла: файл появляется в списке загрузки, размер и тип соответствуют ограничениям.
  3. Прерывание операции: нажатие Esc прерывает перетаскивание и возвращает элемент на место.
  4. Мобильное поведение: перетаскивание на тач-устройстве либо реализовано, либо пользователь получает кнопку “Переместить”.

Когда drag and drop не подходит (контрпример)

  • Много повседневных задач в корпоративных интерфейсах выполняется через клавиатуру — если основная аудитория клавиатурная, drag and drop не заменит полноценной клавиатурной альтернативы.
  • На мобильных устройствах стандартный HTML5 drag and drop часто работает ненадёжно — лучше продумать дополнительные сценарии UX.

Альтернативные подходы и библиотеки

  • Pointer Events / Touch Events: для полного контроля тач-интеракций.
  • Библиотеки: SortableJS, interact.js, Dragula — они решают многие кроссбраузерные и мобильные нюансы.
  • Простой «переместить/вставить» через кнопки: альтернатива для пользователей клавиатуры.

Совместимость и миграция

HTML5 drag and drop хорошо поддерживается в современных десктопных браузерах. Мобильная поддержка менее предсказуема: иногда приходится применять полифиллы или переключаться на pointer/touch-обработчики. При миграции с библиотек учитывайте, что нестандартные реализации могут менять структуру данных в dataTransfer.

Безопасность и приватность

  • Файлы, загруженные через drag and drop, нужно проверять на стороне сервера (антивирус, валидация типов и размеров).
  • Не сохраняйте чувствительные данные в localStorage без шифрования.
  • При обработке метаданных файлов минимизируйте сбор персональных данных; добавьте уведомления для пользователей о правилах обработки.

Шпаргалка (cheat sheet)

  • Начало перетаскивания: dragstart — используйте event.dataTransfer.setData(type, data).
  • Разрешение броска: для drop нужно ev.preventDefault() в dragover/dragenter.
  • Получение данных: event.dataTransfer.getData(type).
  • Получение файлов: event.dataTransfer.files.
  • Пользовательское изображение: event.dataTransfer.setDragImage(img, x, y).

Модель мышления (mental model)

Представляйте drag and drop как пакетную пересылку: источник пакует данные в dataTransfer, браузер переносит «пакет» вместе с визуальным представлением, цель распаковывает и обрабатывает данные. Важны контракты: какие типы данных и как должны интерпретироваться на приёме.

Диаграмма принятия решения

flowchart TD
  A[Нужна ли интерактивность перетаскиванием?] -->|Да| B{Целевая платформа}
  B -->|Десктоп| C[Использовать HTML5 DnD]
  B -->|Мобильные| D[Рассмотреть touch/pointer или библиотеку]
  C --> E[Добавить клавиатурные альтернативы]
  D --> E
  E --> F[Тестирование на accessibility и безопасность]
  F --> G[Внедрение в прод]

Инцидентный план и откат

Если после релиза появились регрессии (зависания при перетаскивании, ошибки загрузки файлов):

  1. Откатить фронтенд-изменение в feature-флаге.
  2. Активировать альтернативный поток (кнопка “Загрузить файл” вместо drag and drop).
  3. Собрать логи и воспроизвести баг на тестовой среде.
  4. Исправить проблему и прогнать тесты доступности и мобильности перед повторным выпуском.

Заключение

Перетаскивание — мощный инструмент взаимодействия, но требует внимания к доступности, безопасности и совместимости. Следуйте методологии: проектируйте UX, реализуйте базовую функциональность, добавьте клавиатурные альтернативы и тщательно протестируйте.

Краткое резюме:

  • Drag and drop базируется на событиях DragEvent и объекте dataTransfer.
  • Нужны preventDefault в dragover/dragenter для разрешения drop.
  • Обязательно реализуйте клавиатурные альтернативы и проверку загружаемых данных.
  • Для мобильных устройств рассмотрите pointer/touch-обработчики или готовые библиотеки.

Важное: тестируйте на реальных устройствах и с ассистивными технологиями, чтобы обеспечить инклюзивность.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Точное разрешение экрана на Mac
macOS

Точное разрешение экрана на Mac

Настройка Siri на HomePod
Руководства

Настройка Siri на HomePod

Ophcrack: как взломать пароль Windows
Security

Ophcrack: как взломать пароль Windows

Как использовать фотоаппарат как веб‑камеру
Оборудование

Как использовать фотоаппарат как веб‑камеру

Кастомизация чекбоксов и радиокнопок в CSS
Веб-разработка

Кастомизация чекбоксов и радиокнопок в CSS

Экспорт и резервное копирование закладок Firefox
Браузеры

Экспорт и резервное копирование закладок Firefox