Стилизация popup и tooltip

Базовая структура всплывающих окон и подсказок

Всплывающие окна (popup) и подсказки (tooltip) в Leaflet представляют собой DOM-элементы, которые добавляются поверх карты и управляются встроенной системой позиционирования. Несмотря на то что они создаются через JavaScript API, их внешний вид полностью контролируется через CSS и дополнительные классы, передаваемые при создании.

Popup формируется как контейнер с несколькими вложенными слоями:

  • внешний контейнер .leaflet-popup
  • «обёртка» содержимого .leaflet-popup-content-wrapper
  • само содержимое .leaflet-popup-content
  • стрелка .leaflet-popup-tip

Tooltip имеет более простую структуру:

  • .leaflet-tooltip
  • дополнительные модификаторы положения (.leaflet-tooltip-top, .leaflet-tooltip-bottom и т.д.)

Эта структура определяет ключевые точки стилизации: фон, рамки, тени, размеры и поведение при позиционировании.


Базовая кастомизация popup через CSS

Основной способ изменения внешнего вида popup — переопределение стандартных классов.

.leaflet-popup-content-wrapper {
  background: #1e1e1e;
  color: #ffffff;
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}

.leaflet-popup-content {
  font-size: 14px;
  line-height: 1.5;
  margin: 10px 14px;
}

.leaflet-popup-tip {
  background: #1e1e1e;
}

Ключевой момент заключается в том, что wrapper и tip должны иметь одинаковый фон, иначе стрелка будет визуально отделяться от окна.


Использование параметра className при создании popup

Leaflet позволяет добавлять собственные CSS-классы, не затрагивая глобальные стили.

L.marker([51.5, -0.09])
  .addTo(map)
  .bindPopup('<b>Объект</b><br>Описание объекта', {
    className: 'custom-popup'
  });

CSS:

.custom-popup .leaflet-popup-content-wrapper {
  background: linear-gradient(135deg, #2b2b2b, #1a1a1a);
  border: 1px solid #444;
}

.custom-popup .leaflet-popup-content {
  color: #f0f0f0;
}

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


Полная переработка внешнего вида popup

При глубокой кастомизации часто требуется изменить не только цвета, но и геометрию элементов.

.leaflet-popup-content-wrapper {
  border-radius: 0;
  padding: 0;
}

.leaflet-popup-content {
  margin: 0;
  padding: 16px;
}

.leaflet-popup-tip {
  width: 14px;
  height: 14px;
  transform: rotate(45deg);
  margin-top: -7px;
}

В этом случае popup начинает напоминать UI-компонент из интерфейса приложения, а не стандартный блок карты.


Управление размерами popup

Размер popup зависит от содержимого, но можно задать ограничения:

.leaflet-popup-content-wrapper {
  max-width: 280px;
  min-width: 180px;
}

.leaflet-popup-content {
  max-height: 200px;
  overflow-y: auto;
}

Такое поведение особенно важно при выводе динамических данных (списки, таблицы, JSON-структуры).


Стилизация tooltip: базовые параметры

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

.leaflet-tooltip {
  background-color: rgba(20, 20, 20, 0.9);
  color: #fff;
  border: none;
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
  font-size: 12px;
  padding: 4px 8px;
}

Tooltip по умолчанию имеет «стрелку», которая также стилизуется через псевдоэлементы:

.leaflet-tooltip:before {
  border-top-color: rgba(20, 20, 20, 0.9);
}

Управление положением tooltip

При создании tooltip можно задавать направление и поведение:

marker.bindTooltip('Подпись', {
  permanent: true,
  direction: 'top',
  offset: [0, -10]
});

Влияние параметров:

  • direction — определяет сторону отображения (top, bottom, left, right, center)
  • offset — смещение относительно точки привязки
  • permanent — фиксированное отображение без hover
  • sticky — следование за курсором

Эти параметры напрямую влияют на применяемые CSS-классы (leaflet-tooltip-top, leaflet-tooltip-bottom и т.д.), что позволяет строить адаптивную стилизацию.


Различие стилизации popup и tooltip

Popup и tooltip используют разные подходы к визуальной плотности:

  • popup ориентирован на контент и сложные структуры
  • tooltip — на минимальные текстовые метки

Это отражается в CSS:

  • popup имеет более сложную DOM-структуру
  • tooltip зависит от псевдоэлементов и компактных отступов

Использование HTML внутри popup и влияние на стили

Popup поддерживает произвольный HTML, что позволяет внедрять сложные интерфейсные элементы.

L.marker([51.5, -0.09]).addTo(map).bindPopup(`
  <div class="card">
    <h3>Объект</h3>
    <p>Описание</p>
    <button class="action">Подробнее</button>
  </div>
`);

CSS:

.card h3 {
  margin: 0 0 8px;
  font-size: 16px;
}

.card .action {
  background: #3b82f6;
  border: none;
  padding: 6px 10px;
  color: white;
  border-radius: 4px;
  cursor: pointer;
}

Важно учитывать, что popup не изолирует стили, поэтому глобальные CSS-правила могут влиять на его содержимое.


Управление анимацией появления

Popup использует CSS-анимацию через класс .leaflet-fade-anim:

.leaflet-fade-anim .leaflet-popup {
  transition: opacity 0.2s ease, transform 0.2s ease;
}

Можно переопределять поведение:

.leaflet-popup {
  transition: none;
}

Отключение анимации часто применяется в высоконагруженных приложениях или при синхронном обновлении данных.


Темизация через переменные и модульные стили

При масштабных проектах стили popup и tooltip обычно выносятся в систему тем:

:root {
  --popup-bg: #1f2937;
  --popup-text: #f9fafb;
  --tooltip-bg: rgba(17, 24, 39, 0.9);
}

.leaflet-popup-content-wrapper {
  background: var(--popup-bg);
  color: var(--popup-text);
}

.leaflet-tooltip {
  background: var(--tooltip-bg);
}

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


Тонкая настройка стрелки popup

Стрелка popup (.leaflet-popup-tip) часто требует отдельной корректировки при нестандартных дизайнах:

.leaflet-popup-tip {
  border: 1px solid #444;
  box-shadow: none;
}

При изменении углов скругления важно синхронизировать форму tip с контейнером, иначе возникает визуальный разрыв между элементами.


Сложные кейсы: динамическая стилизация через JS

Иногда стили зависят от данных объекта:

const severityClass = severity === 'high'
  ? 'popup-high'
  : 'popup-normal';

L.marker([51.5, -0.09])
  .addTo(map)
  .bindPopup(`<div class="${severityClass}">Событие</div>`);

CSS:

.popup-high {
  border-left: 4px solid #ef4444;
}

.popup-normal {
  border-left: 4px solid #22c55e;
}

Такой подход позволяет связывать визуальный стиль с состоянием данных.


Поведение при масштабировании карты

Popup и tooltip автоматически пересчитывают позицию при изменении масштаба карты. Однако стили могут влиять на производительность:

  • большие box-shadow увеличивают нагрузку при перерисовке
  • сложные градиенты могут замедлять рендер
  • анимации transform требуют GPU-ускорения

Оптимизированные стили обычно минимизируют визуальные эффекты и используют простые цвета и тени.