Классы и идентификаторы элементов

DOM-структура Leaflet строится вокруг заранее определённого набора CSS-классов и нескольких ключевых идентификаторов контейнеров, через которые библиотека управляет визуализацией карты, слоями и интерактивными элементами. Понимание системы классов и идентификаторов критично для кастомизации интерфейса, стилизации элементов и интеграции карты в сложные веб-приложения.

Инициализация карты всегда привязывается к DOM-элементу, который становится корневым контейнером Leaflet:

const map = L.map('map');

В этом случае строка 'map' соответствует id HTML-элемента:

<div id="map"></div>

Leaflet использует этот id исключительно как точку привязки. После инициализации контейнер получает дополнительные классы, которые формируют базовую структуру отображения:

  • leaflet-container — основной класс карты
  • leaflet-touch — добавляется на сенсорных устройствах
  • leaflet-fade-anim, leaflet-grab, leaflet-dragging — динамические классы состояния

Идентификатор (id) остаётся неизменным и используется только для получения ссылки на контейнер, тогда как классы управляют внешним видом и поведением.

DOM-структура и служебные классы

После создания карты Leaflet формирует вложенную структуру элементов:

div.leaflet-container
 ├── div.leaflet-pane
 ├── div.leaflet-pane
 ├── div.leaflet-control-container
 └── div.leaflet-shadow-pane (и другие слои)

Каждый элемент в этой структуре имеет строго определённую роль и класс.

Панели (Panes)

Система panes — основа визуального порядка слоёв карты. Все объекты (тайлы, маркеры, попапы) размещаются внутри отдельных контейнеров:

  • leaflet-map-pane — общий контейнер трансформаций
  • leaflet-tile-pane — слой тайлов
  • leaflet-overlay-pane — векторные слои (GeoJSON, polyline, polygon)
  • leaflet-shadow-pane — тени маркеров
  • leaflet-marker-pane — маркеры
  • leaflet-tooltip-pane — подсказки
  • leaflet-popup-pane — всплывающие окна

Каждый pane имеет собственный z-index, что определяет порядок наложения элементов. Например, маркеры всегда находятся выше тайлов, а popups — выше маркеров.

.leaflet-marker-pane {
    z-index: 600;
}

.leaflet-popup-pane {
    z-index: 700;
}

Изменение этих классов напрямую влияет на визуальную иерархию карты.

Классы тайлового слоя

Тайлы создаются внутри leaflet-tile-pane и получают класс:

  • leaflet-tile — каждый тайловый элемент
  • leaflet-tile-loaded — загруженный тайл
  • leaflet-fade-anim — анимация появления

CSS управление тайлами позволяет влиять на визуальное качество загрузки:

.leaflet-tile {
    filter: contrast(1.1) saturate(1.2);
}

Маркеры и классические иконки

Маркеры используют класс leaflet-marker-icon и leaflet-marker-shadow. Однако ключевую роль играет DivIcon, который позволяет задавать пользовательские классы:

const icon = L.divIcon({
    className: 'custom-marker'
});

В DOM это преобразуется в:

<div class="leaflet-marker-icon custom-marker"></div>

Таким образом, className в DivIcon становится основным механизмом стилизации кастомных маркеров.

Типичные классы маркеров:

  • leaflet-div-icon
  • leaflet-interactive
  • пользовательские классы из className

Векторные слои и SVG-классы

Векторные объекты (Polyline, Polygon, Circle) используют SVG-элементы внутри leaflet-overlay-pane. Для них применяется параметр className:

L.polyline(latlngs, {
    className: 'route-line'
});

В DOM это становится:

<path class="leaflet-interactive route-line"></path>

Базовые классы:

  • leaflet-interactive — включает обработку событий мыши
  • leaflet-clickable — устаревший, но встречающийся в некоторых версиях
  • пользовательские классы для стилизации

SVG-структура позволяет использовать сложные селекторы:

.route-line {
    stroke: red;
    stroke-width: 3;
}

Попапы и тултипы

Попапы и тултипы формируют отдельные DOM-узлы внутри своих pane:

Попап:

  • leaflet-popup
  • leaflet-zoom-animated
  • leaflet-popup-content-wrapper
  • leaflet-popup-content

Тултип:

  • leaflet-tooltip
  • leaflet-tooltip-top, leaflet-tooltip-bottom и т.д.

Пример структуры попапа:

<div class="leaflet-popup">
    <div class="leaflet-popup-content-wrapper">
        <div class="leaflet-popup-content"></div>
    </div>
</div>

Кастомизация осуществляется через переопределение классов:

.leaflet-popup-content-wrapper {
    background: #1e1e1e;
    color: #fff;
    border-radius: 8px;
}

Контролы интерфейса

UI-элементы управления картой используют систему классов leaflet-control:

  • leaflet-control
  • leaflet-bar
  • leaflet-control-zoom
  • leaflet-control-attribution
  • leaflet-control-layers

Структура zoom-контрола:

<div class="leaflet-control-zoom leaflet-bar leaflet-control">
    <a class="leaflet-control-zoom-in"></a>
    <a class="leaflet-control-zoom-out"></a>
</div>

CSS-иерархия контролов позволяет унифицировать внешний вид всех элементов управления:

.leaflet-bar a {
    background-color: #333;
    color: #fff;
}

Пользовательские классы через опции слоёв

Leaflet предоставляет возможность задавать классы на уровне слоя:

const geojson = L.geoJSON(data, {
    className: 'geo-layer'
});

Это особенно важно для массовой стилизации объектов через CSS, без необходимости обработки каждого элемента отдельно.

Работа с контейнером через getContainer

Каждый объект карты предоставляет доступ к корневому DOM-элементу:

map.getContainer();

Контейнер всегда содержит класс:

  • leaflet-container

Прямое использование идентификатора и класса позволяет строить глобальные стили:

#map {
    height: 500px;
}

.leaflet-container {
    background: #000;
}

Идентификаторы и множественные карты

При создании нескольких карт каждый контейнер должен иметь уникальный id:

<div id="map1"></div>
<div id="map2"></div>
L.map('map1');
L.map('map2');

Leaflet не генерирует новые id, поэтому управление множественными экземплярами полностью зависит от структуры DOM.

Панели и кастомные panes

Leaflet позволяет создавать собственные panes:

map.createPane('customPane');

После создания автоматически формируется класс:

  • leaflet-pane leaflet-customPane-pane

Стилизация:

.leaflet-customPane-pane {
    z-index: 650;
}

Это ключевой механизм управления порядком отображения без вмешательства в стандартные слои.

CSS-конфликты и нейминг

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

  • предпочтительно использовать префиксы приложения (app-, map-, geo-)
  • не переопределять глобальные классы без необходимости
  • не изменять напрямую leaflet-container, если не требуется глобальная тема

Пример безопасного расширения:

.geo-highlight {
    fill: yellow;
    opacity: 0.6;
}

Событийная привязка к классам

DOM-события Leaflet часто завязаны на класс leaflet-interactive. Элементы без него не реагируют на pointer-события.

L.circle([50, 30], {
    className: 'clickable-circle'
});

Если элемент не получает leaflet-interactive, он остаётся визуальным, но не интерактивным.

Зависимость z-index от классов panes

Каждый pane имеет фиксированную систему слоёв:

  • tile pane — базовый уровень
  • overlay pane — геометрия
  • marker pane — точки
  • popup pane — всплывающие окна

Изменение z-index через CSS классы напрямую влияет на перекрытие объектов, но может нарушить предсказуемость отображения при сложных композициях слоёв.

.leaflet-overlay-pane {
    z-index: 400;
}

Такая модификация применяется только при необходимости переопределения стандартной логики визуализации.