Создание кастомной темы

Pikaday строится вокруг набора предсказуемых CSS-классов, которые описывают структуру календаря. Вся кастомизация внешнего вида сводится к переопределению этих классов и управлению их контекстом через дополнительные обёртки или классы-метки.

Ключевая особенность подхода заключается в том, что библиотека не навязывает дизайн через JavaScript, а полностью делегирует внешний вид CSS-слою. Это делает систему темизации гибкой, но требовательной к дисциплине в структуре стилей.

Основные элементы разметки:

  • .pika-single — контейнер календаря
  • .pika-lendar — внутренний блок календаря
  • .pika-title — заголовок месяца и навигация
  • .pika-prev, .pika-next — кнопки переключения месяцев
  • .pika-table — таблица дней
  • .pika-button — отдельный день
  • .is-selected, .is-today, .is-disabled — состояния элементов

Каждый из этих классов является точкой расширения для кастомной темы.


Базовое переопределение стилей

Создание кастомной темы начинается с переопределения стандартного CSS, который поставляется вместе с Pikaday. В большинстве случаев используется либо полное копирование исходного файла стилей, либо точечное переопределение ключевых параметров.

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

.pika-single {
  border-radius: 12px;
  border: 1px solid #2b2b2b;
  background: #1e1e1e;
  color: #ffffff;
  font-family: Inter, sans-serif;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
}

.pika-title {
  background: transparent;
  color: #ffffff;
  padding: 10px;
  text-align: center;
}

.pika-button {
  background: transparent;
  color: #e0e0e0;
  border-radius: 6px;
  transition: background 0.2s ease;
}

.pika-button:hover {
  background: rgba(255, 255, 255, 0.08);
}

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


Управление состояниями элементов

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

Основные состояния:

  • .is-selected — выбранная дата
  • .is-today — текущий день
  • .is-disabled — недоступные даты
  • .is-inrange — диапазон (при использовании range-подобных решений)
  • .is-startrange, .is-endrange — границы диапазона

Пример кастомизации состояний:

.is-selected .pika-button {
  background: #4f7cff;
  color: #ffffff;
  font-weight: 600;
}

.is-today .pika-button {
  border: 1px solid #4f7cff;
}

.is-disabled .pika-button {
  opacity: 0.3;
  cursor: not-allowed;
}

Особое внимание требуется к .is-selected, так как именно он определяет основной акцент темы.


Темизация через обёртку класса

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

const picker = new Pikaday({
  field: document.querySelector('#input'),
  className: 'calendar-theme-dark'
});

После этого все стили темы можно изолировать:

.calendar-theme-dark.pika-single {
  background: #121212;
  border-color: #333;
}

.calendar-theme-dark .pika-title {
  color: #f5f5f5;
}

.calendar-theme-dark .pika-button {
  color: #d0d0d0;
}

Такой подход позволяет:

  • использовать несколько тем одновременно
  • избегать конфликтов глобальных стилей
  • управлять темой через JavaScript

Темизация через data-атрибуты

Альтернативный способ заключается в использовании data-theme, который устанавливается на родительский контейнер страницы или отдельный wrapper.

<div data-theme="dark">
  <input id="input">
</div>

CSS:

[data-theme="dark"] .pika-single {
  background: #111;
  color: #fff;
}

[data-theme="light"] .pika-single {
  background: #ffffff;
  color: #111;
}

Такой метод особенно полезен в приложениях с глобальной системой тем (например, переключение light/dark режима).


Работа с приоритетами CSS

При кастомизации Pikaday часто возникает проблема специфичности стандартных стилей. Библиотека использует достаточно конкретные селекторы, поэтому простые переопределения могут не применяться.

Стратегии решения:

Повышение специфичности

.calendar-theme-dark .pika-single .pika-table .pika-button {
  color: #eaeaea;
}

Использование каскадного слоя переопределений

.pika-single {
  all: unset;
}

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

Подключение стилей после оригинальных

Порядок подключения CSS-файлов часто решает проблему без увеличения специфичности.


Кастомизация навигации календаря

Заголовок месяца и кнопки переключения являются отдельной зоной стилизации.

.pika-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px;
}

.pika-prev,
.pika-next {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
}

Часто применяется замена стандартных стрелок:

.pika-prev:before {
  content: '‹';
  font-size: 18px;
}

.pika-next:before {
  content: '›';
  font-size: 18px;
}

Более сложные темы используют SVG-иконки через background-image.


Грид и сетка дней

Таблица дней .pika-table может быть преобразована в более современную сетку, визуально приближенную к flex/grid-структурам.

.pika-table {
  width: 100%;
  border-collapse: collapse;
}

.pika-table th {
  font-size: 12px;
  color: #888;
  padding-bottom: 8px;
}

Каждая ячейка недели может быть адаптирована:

.pika-button {
  width: 32px;
  height: 32px;
  line-height: 32px;
  border-radius: 8px;
  display: inline-block;
  text-align: center;
}

Поддержка двух и более тем в одном приложении

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

Подход через модификатор класса:

function setCalendarTheme(picker, theme) {
  const root = picker.el;
  root.classList.remove('theme-light', 'theme-dark');
  root.classList.add(theme);
}

CSS:

.theme-light.pika-single {
  background: #fff;
  color: #000;
}

.theme-dark.pika-single {
  background: #1a1a1a;
  color: #fff;
}

Интеграция с препроцессорами

Использование SASS или LESS упрощает поддержку сложных тем.

Пример структуры SASS:

$pika-dark-bg: #121212;
$pika-dark-text: #eaeaea;

.calendar-theme-dark {
  .pika-single {
    background: $pika-dark-bg;
    color: $pika-dark-text;
  }

  .pika-button {
    color: lighten($pika-dark-text, 10%);
  }
}

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

  • централизованные переменные
  • переиспользование цветовых схем
  • упрощение масштабирования тем

Анимации и микровзаимодействия

Темизация Pikaday часто включает не только цветовые изменения, но и поведенческие улучшения.

.pika-single {
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.pika-single.is-bound {
  opacity: 1;
  transform: translateY(0);
}

Дополнительные эффекты:

.pika-button {
  transition: background 0.15s ease, transform 0.1s ease;
}

.pika-button:active {
  transform: scale(0.95);
}

Изоляция стилей в больших приложениях

В крупных системах важно предотвращать утечки стилей Pikaday в глобальную область и наоборот.

Подходы:

  • CSS Modules
  • BEM-нейминг поверх Pikaday-классов
  • Shadow DOM-обёртка (ограниченно применимо)
  • scoped styles в рамках фреймворков

Пример BEM-обёртки:

.datepicker__calendar .pika-single {
  font-size: 14px;
}

Поддержка адаптивных тем

Темы должны учитывать мобильные устройства:

@media (max-width: 480px) {
  .pika-single {
    width: 100%;
    border-radius: 0;
  }

  .pika-button {
    width: 36px;
    height: 36px;
  }
}

Работа с контрастом и доступностью

При создании кастомной темы необходимо учитывать контрастность:

.pika-button {
  color: #e0e0e0;
  background: transparent;
}

.pika-button:focus {
  outline: 2px solid #4f7cff;
}

Состояния focus особенно важны при навигации с клавиатуры.


Стратегии построения дизайн-системы на основе Pikaday

В системных интерфейсах Pikaday становится частью дизайн-токенов:

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

Пример интеграции:

:root {
  --color-primary: #4f7cff;
  --radius-md: 8px;
}

.pika-button {
  border-radius: var(--radius-md);
}

.is-selected .pika-button {
  background: var(--color-primary);
}

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