Семантическая разметка

Shopify Draggable — это мощная библиотека для реализации перетаскивания элементов на веб-страницах. Один из ключевых аспектов её использования — правильная семантическая разметка HTML, которая обеспечивает корректную работу функционала и доступность для пользователей.

Контейнеры и элементы

В Draggable различают два основных типа элементов: контейнеры (containers) и элементы (items). Контейнеры служат обрамляющими блоками, внутри которых расположены перетаскиваемые элементы.

Пример базовой структуры:

<ul class="draggable-container">
  <li class="draggable-item">Элемент 1</li>
  <li class="draggable-item">Элемент 2</li>
  <li class="draggable-item">Элемент 3</li>
</ul>
  • .draggable-container — контейнер, в котором можно перемещать элементы.
  • .draggable-item — отдельный перетаскиваемый элемент.

Важно: использование семантически корректных тегов (ul/ol для списков, div для блоков, section или article для областей контента) повышает доступность и упрощает работу с Draggable.

Адаптация для доступности

Для обеспечения доступности (accessibility) следует добавлять ARIA-атрибуты:

  • role="list" для контейнера, если это список.
  • role="listitem" для каждого элемента.
  • aria-grabbed="true/false" для индикатора состояния перетаскивания.
  • aria-dropeffect="move" для контейнера, указывающего, что элемент может быть перемещён.

Пример разметки с ARIA:

<ul class="draggable-container" role="list" aria-dropeffect="move">
  <li class="draggable-item" role="listitem" aria-grabbed="false">Элемент 1</li>
  <li class="draggable-item" role="listitem" aria-grabbed="false">Элемент 2</li>
  <li class="draggable-item" role="listitem" aria-grabbed="false">Элемент 3</li>
</ul>

Draggable автоматически обновляет атрибут aria-grabbed при начале и завершении перетаскивания.

Инициализация Draggable с семантической разметкой

Для связывания Draggable с разметкой используется конструктор Draggable. В нём указывается контейнер и селектор элементов:

import { Draggable } from '@shopify/draggable';

const container = document.querySelector('.draggable-container');

const draggable = new Draggable(container, {
  draggable: '.draggable-item',
  mirror: {
    constrainDimensions: true,
  },
});

Ключевые моменты:

  • draggable — селектор, соответствующий классу элементов.
  • mirror — опции зеркального отображения при перетаскивании, полезно для сохранения размера и стиля исходного элемента.
  • Semantics обеспечиваются правильной разметкой контейнера и элементов, не изменяя поведение Draggable.

Поддержка вложенных контейнеров

Draggable поддерживает вложенные контейнеры, позволяя перемещать элементы между ними. Семантическая разметка должна повторять ту же структуру для каждого уровня:

<div class="draggable-container" role="list">
  <div class="draggable-item" role="listitem">Элемент A
    <div class="draggable-container" role="list">
      <div class="draggable-item" role="listitem">Подэлемент A1</div>
      <div class="draggable-item" role="listitem">Подэлемент A2</div>
    </div>
  </div>
  <div class="draggable-item" role="listitem">Элемент B</div>
</div>

Оптимизация с точки зрения SEO и DOM

  • Использование семантических тегов (ul, ol, li, section, article) помогает поисковым системам правильно индексировать контент.
  • Поддержка логической иерархии элементов облегчает работу с Draggable и снижает вероятность ошибок при динамическом перемещении элементов.
  • Избегание лишних div и span повышает читаемость DOM и снижает нагрузку на обработку событий Draggable.

Работа с динамически добавляемыми элементами

При динамическом добавлении элементов необходимо:

  1. Обновить контейнеры и селекторы.
  2. Убедиться, что новые элементы имеют правильные ARIA-атрибуты.
  3. При необходимости вызвать метод draggable.destroy() и заново инициализировать Draggable для корректной работы с новыми элементами.

Пример добавления нового элемента:

const newItem = document.createElement('li');
newItem.className = 'draggable-item';
newItem.setAttribute('role', 'listitem');
newItem.setAttribute('aria-grabbed', 'false');
newItem.textContent = 'Элемент 4';

container.appendChild(newItem);
draggable.destroy();
draggable = new Draggable(container, { draggable: '.draggable-item' });

Использование data-атрибутов для семантики

Draggable допускает использование data- атрибутов для идентификации и хранения метаданных:

<li class="draggable-item" role="listitem" data-id="101" aria-grabbed="false">Элемент 1</li>
  • data-id может использоваться для синхронизации с серверной базой или внутренней логикой приложения.
  • Поддерживает сложные сценарии, например, сортировку или фильтрацию без нарушения семантической структуры.

Итоговые рекомендации по семантической разметке

  • Каждый контейнер должен быть логически обоснованным (ul, ol, div, section).
  • Каждый элемент — самодостаточной единицей контента с role="listitem" или эквивалентным.
  • ARIA-атрибуты — обязательны для обеспечения доступности.
  • Использовать вложенные контейнеры корректно, повторяя семантическую структуру.
  • Динамически добавленные элементы должны соответствовать тем же правилам разметки.

Правильная семантика не только обеспечивает удобство использования Draggable, но и повышает доступность, SEO и стабильность работы библиотеки в сложных интерфейсах.