Темная и светлая темы

Библиотека Tippy.js предоставляет гибкую систему тем (themes), позволяющую полностью контролировать внешний вид всплывающих подсказок. Темы реализуются через CSS-классы и тесно связаны с архитектурой Popper-элемента, который Tippy использует для позиционирования.

Тема задаётся через параметр theme и автоматически добавляет CSS-класс вида:

.tippy-box[data-theme~='имя-темы']

Это означает, что одна подсказка может использовать несколько тем одновременно.


Базовая светлая тема

По умолчанию Tippy использует светлую тему, которая визуально соответствует классическим tooltip-компонентам:

tippy('.btn', {
  content: 'Подсказка',
  theme: 'light'
});

Ключевые особенности светлой темы:

  • светлый фон (#fff)
  • тёмный текст
  • мягкая тень
  • нейтральная палитра

Пример базовой стилизации:

.tippy-box[data-theme~='light'] {
  background-color: #ffffff;
  color: #333;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1);
}

Стрелка (arrow) также требует стилизации:

.tippy-box[data-theme~='light'][data-placement^='top'] > .tippy-arrow::before {
  border-top-color: #ffffff;
}

Темная тема

Темная тема используется в интерфейсах с низкой освещённостью или в приложениях с dark mode:

tippy('.btn', {
  content: 'Темная подсказка',
  theme: 'dark'
});

Пример оформления:

.tippy-box[data-theme~='dark'] {
  background-color: #1f2937;
  color: #f9fafb;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
}

Стрелка:

.tippy-box[data-theme~='dark'][data-placement^='top'] > .tippy-arrow::before {
  border-top-color: #1f2937;
}

Особенности:

  • высокий контраст текста
  • более выраженные тени
  • отсутствие ярких цветов

Переключение между светлой и тёмной темами

На практике тема часто зависит от состояния интерфейса (например, системной темы пользователя или переключателя в приложении).

Динамическое обновление

const instance = tippy('.btn', {
  content: 'Подсказка',
  theme: 'light'
});

// смена темы
instance.setProps({
  theme: 'dark'
});

Привязка к классу на <body>

const isDark = document.body.classList.contains('dark');

tippy('.btn', {
  content: 'Подсказка',
  theme: isDark ? 'dark' : 'light'
});

Использование нескольких тем

Tippy позволяет комбинировать темы:

tippy('.btn', {
  content: 'Комбинированная тема',
  theme: 'dark rounded'
});

CSS:

.tippy-box[data-theme~='rounded'] {
  border-radius: 12px;
}

Комбинации позволяют:

  • разделить цветовую схему и форму
  • переиспользовать стили
  • создавать модульные темы

Кастомные темы

Создание собственной темы — основной механизм кастомизации.

tippy('.btn', {
  content: 'Своя тема',
  theme: 'custom'
});
.tippy-box[data-theme~='custom'] {
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  color: white;
  font-weight: 500;
}

Работа со стрелкой (arrow)

Стрелка — отдельный элемент, требующий синхронизации с темой.

Структура:

<div class="tippy-box" data-theme="dark">
  <div class="tippy-content"></div>
  <div class="tippy-arrow"></div>
</div>

Стилизация зависит от направления:

/* сверху */
[data-placement^='top'] .tippy-arrow::before {
  border-top-color: #1f2937;
}

/* снизу */
[data-placement^='bottom'] .tippy-arrow::before {
  border-bottom-color: #1f2937;
}

Важно учитывать:

  • цвет стрелки должен совпадать с фоном
  • иначе возникает визуальный разрыв

Адаптация под системную тему

Современные интерфейсы часто используют media query:

@media (prefers-color-scheme: dark) {
  .tippy-box[data-theme~='auto'] {
    background-color: #111827;
    color: #f3f4f6;
  }
}

JS:

tippy('.btn', {
  content: 'Авто тема',
  theme: 'auto'
});

Использование CSS-переменных

Для масштабируемых проектов удобнее использовать переменные:

:root {
  --tooltip-bg: #ffffff;
  --tooltip-color: #222;
}

.dark {
  --tooltip-bg: #1f2937;
  --tooltip-color: #f9fafb;
}

.tippy-box {
  background-color: var(--tooltip-bg);
  color: var(--tooltip-color);
}

Преимущества:

  • централизованное управление
  • простое переключение темы
  • уменьшение дублирования CSS

Анимации и темы

Темы могут влиять не только на цвета, но и на поведение:

.tippy-box[data-theme~='dark'] {
  transition: transform 0.2s ease, opacity 0.2s ease;
}

Комбинация с параметром:

tippy('.btn', {
  animation: 'scale',
  theme: 'dark'
});

Интеграция с фреймворками

React

<Tippy content="Подсказка" theme={isDark ? 'dark' : 'light'}>
  <button>Наведи</button>
</Tippy>

Vue

<tippy :content="'Подсказка'" :theme="isDark ? 'dark' : 'light'">
  <button>Наведи</button>
</tippy>

Распространённые ошибки

Несоответствие стрелки и фона

  • забывают стилизовать ::before

Конфликт тем

  • одинаковые CSS-правила перекрывают друг друга

Отсутствие контраста

  • тёмный текст на тёмном фоне

Жёстко заданные цвета

  • усложняют переключение темы

Рекомендации по проектированию тем

  • разделять структуру и оформление (layout vs theme)
  • использовать CSS-переменные
  • проектировать темы как независимые модули
  • учитывать доступность (contrast ratio)
  • тестировать на разных фонах

Минимальный универсальный набор тем

/* светлая */
.tippy-box[data-theme~='light'] {
  background: #fff;
  color: #222;
}

/* тёмная */
.tippy-box[data-theme~='dark'] {
  background: #111;
  color: #eee;
}

/* скруглённая */
.tippy-box[data-theme~='rounded'] {
  border-radius: 10px;
}

Комбинирование:

theme: 'dark rounded'

Расширение тем через data-атрибуты

Tippy активно использует data-*:

.tippy-box[data-theme~='dark'][data-placement^='right'] {
  margin-left: 8px;
}

Это позволяет:

  • адаптировать тему под позицию
  • создавать сложные UI-эффекты

Производительность

Темы не влияют напрямую на производительность JS, но:

  • сложные тени и blur могут нагружать GPU
  • большое количество уникальных тем увеличивает CSS

Оптимизация:

  • переиспользование классов
  • минимизация эффектов
  • использование переменных вместо дублирования

Архитектура тем в больших проектах

Рекомендуемая структура:

/styles
  /tippy
    base.css
    light.css
    dark.css
    themes/
      success.css
      warning.css

Подключение:

theme: 'dark success'

Такой подход:

  • масштабируется
  • упрощает поддержку
  • облегчает внедрение дизайн-системы