Экранные читалки интерпретируют DOM-структуру веб-страницы, превращая визуальные интерфейсы в последовательное текстовое представление. Интерактивные карты представляют для таких систем сложную среду: динамическое содержимое, графические тайлы, множество слоёв, событийно-ориентированное взаимодействие.
Картографические библиотеки, основанные на canvas и div-тайлах, не предоставляют семантической информации автоматически. Поэтому доступность формируется через:
В Leaflet доступность реализуется частично на уровне ядра и частично на уровне прикладного кода.
Основная проблема карт — отсутствие семантики у визуального слоя. Контейнер карты должен быть интерпретируемым как единый интерактивный объект.
Типичная конфигурация:
role="application" или role="region"aria-label с описанием назначения картыtabindex="0" для включения в порядок фокуса<div id="map"
role="application"
aria-label="Интерактивная карта с объектами"
tabindex="0"></div>
role="application" применяется только при необходимости
полного перехвата клавиатуры, поскольку он изменяет поведение экранной
читалки, переводя её в режим взаимодействия с приложением.
role="region" предпочтительнее, если карта используется
как вспомогательный элемент страницы.
Экранные читалки зависят от логического порядка фокуса. Карта как единый элемент не должна «перехватывать» фокус без необходимости, но должна позволять вход и выход из режима взаимодействия.
Основные принципы:
TabEsc (в кастомной логике)Пример обработчика:
map.getContainer().addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
map.getContainer().blur();
}
});
Фокусировка на контейнере карты должна быть минимально навязчивой и предсказуемой.
Слепые и слабовидящие пользователи не могут интерпретировать визуальные тайлы. Поэтому карта должна дублироваться структурированным списком объектов.
Подходы:
ul > li)Пример структуры:
<ul aria-label="Список объектов на карте">
<li>Библиотека — координаты 51.1605, 71.4704</li>
<li>Музей — координаты 51.1470, 71.4320</li>
</ul>
Такой список может обновляться синхронно с картой.
Каждый маркер должен иметь доступное текстовое представление. В Leaflet маркеры создаются как DOM-элементы, что позволяет назначать атрибуты напрямую.
const marker = L.marker([51.1605, 71.4704])
.addTo(map)
.bindTooltip("Библиотека");
marker.getElement().setAttribute("role", "button");
marker.getElement().setAttribute("aria-label", "Библиотека, координаты 51.1605 71.4704");
Важно учитывать:
aria-labelКарты постоянно изменяют состояние: перемещение, масштабирование, фильтрация слоёв. Экранные читалки не отслеживают такие изменения автоматически.
Используются aria-live области:
<div aria-live="polite" id="map-status" class="visually-hidden"></div>
Обновления:
map.on('moveend', () => {
const center = map.getCenter();
document.getElementById('map-status').textContent =
`Центр карты изменён: ${center.lat.toFixed(4)}, ${center.lng.toFixed(4)}`;
});
Типы live regions:
polite — ненавязчивое обновлениеassertive — прерывающее (используется редко)Слои в Leaflet часто содержат множество объектов. Для экранных читалок важна иерархия:
ARIA-структура слоя:
<div role="group" aria-label="Объекты инфраструктуры">
<button aria-pressed="true">Показать больницы</button>
</div>
Экранные читалки тесно связаны с клавиатурной навигацией. Карта должна поддерживать:
Enter и
SpaceРекомендуемая модель:
Tab — переход к картеEnter — активация объектаEsc — выход из режима картыИзменение масштаба карты должно иметь текстовое сопровождение. Без этого экранная читалка не фиксирует изменения.
map.on('zoomend', () => {
const zoom = map.getZoom();
statusEl.textContent = `Масштаб карты изменён: уровень ${zoom}`;
});
При сложных интерфейсах дополнительно фиксируется:
Некоторые функции карты невозможно адекватно интерпретировать через экранную читалку без альтернатив:
Пример маршрута:
<ol aria-label="Маршрут">
<li>Старт: 51.1605, 71.4704</li>
<li>Поворот на север</li>
<li>Финиш: 51.1470, 71.4320</li>
</ol>
Базовая реализация Leaflet не предоставляет полноценную доступность из коробки:
Поэтому доступность формируется поверх библиотеки, а не внутри неё.
Технический слой доступности часто использует скрытые элементы:
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
overflow: hidden;
clip: rect(0 0 0 0);
}
Используется для:
Экранная читалка воспринимает интерфейс как последовательность состояний. Карта должна сохранять синхронизацию между:
Несогласованность приводит к потере контекста: пользователь слышит устаревшие данные при актуальном визуальном отображении.
Popup и tooltip требуют отдельной семантики:
marker.bindPopup("Объект инфраструктуры", {
ariaLabel: "Информация об объекте инфраструктуры"
});
Рекомендации:
Наиболее устойчивый подход к доступности карт — разделение:
Панель синхронизируется с картой:
Такой подход компенсирует ограничения визуального слоя и обеспечивает стабильную работу экранных читалок.