Стилизация выбранной даты

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

Основной принцип заключается в том, что каждая дата в сетке календаря является отдельным DOM-элементом, обычно <td> с вложенной кнопкой или <button>, и именно к этому элементу применяется класс, обозначающий состояние выбора.

Ключевой класс для выбранного дня:

  • is-selected — применяется к дате, которая совпадает с текущим значением selectedDate

Дополнительно могут использоваться состояния:

  • is-today — текущая дата системы
  • is-disabled — недоступные даты
  • is-outside-current-month — дни соседних месяцев

Комбинация этих классов формирует итоговый визуальный стиль ячейки.


Базовая структура DOM и влияние на стили

Каждый календарный месяц в Pikaday строится как таблица:

  • <table class="pika-table">
  • <tbody>
  • <tr> — неделя
  • <td> — день

Внутри ячейки обычно присутствует интерактивный элемент:

<td class="is-selected is-today">
  <button class="pika-button pika-day">15</button>
</td>

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

  • контейнер состояния (td)
  • интерактивный элемент (button)
  • визуальную часть (CSS)

Именно класс is-selected определяет внешний вид выбранного дня.


Базовая стилизация выбранной даты

Стандартное оформление выбранной даты обычно задаётся через переопределение CSS:

.pika-table td.is-selected .pika-button {
    background: #2d6cdf;
    color: #ffffff;
    border-radius: 4px;
}

В этой модели важны три аспекта:

  1. Селектор через родителя

    • состояние хранится на td
    • стиль применяется к button
  2. Приоритет состояния

    • is-selected должен перекрывать is-today
    • требуется более специфичный селектор
  3. Изоляция интерактивности

    • стили не ломают hover/focus состояния

Сочетание состояний: selected + today

Частая ситуация — выбранная дата совпадает с текущим днём. Pikaday добавляет оба класса одновременно:

<td class="is-selected is-today">

Без дополнительной настройки возникает конфликт визуальных правил.

Корректная стратегия:

.pika-table td.is-selected.is-today .pika-button {
    background: #1f4fa3;
    color: #fff;
}

Логика приоритетов:

  • is-selected имеет приоритет над is-today
  • комбинированный селектор перекрывает оба состояния

Hover и взаимодействие с выбранной датой

Проблема стилизации часто возникает при наведении курсора на уже выбранный день. Pikaday применяет hover к кнопке:

.pika-button:hover {
    background: #e6f0ff;
}

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

Правильная компенсация:

.pika-table td.is-selected .pika-button:hover {
    background: #2d6cdf;
    color: #ffffff;
}

Или более строгий вариант:

.pika-table td.is-selected .pika-button,
.pika-table td.is-selected .pika-button:hover {
    background: #2d6cdf;
    color: #ffffff;
}

Фокус состояния и клавиатурная навигация

Pikaday поддерживает навигацию с клавиатуры, что приводит к появлению focus на кнопке:

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

При совпадении с выбранной датой важно избежать визуального конфликта между focus и selected.

Распространённый подход:

.pika-table td.is-selected .pika-button:focus {
    outline: none;
}

Или сохранение outline, но с адаптацией цвета:

.pika-table td.is-selected .pika-button:focus {
    outline: 2px solid #ffffff;
    box-shadow: 0 0 0 2px #2d6cdf;
}

Стилизация через модификацию theme

Pikaday позволяет задавать кастомные темы через theme-класс, который добавляется к корневому контейнеру календаря:

new Pikaday({
    field: document.getElementById('date'),
    theme: 'dark-theme'
});

Это даёт возможность изолировать стили выбранной даты в рамках темы:

.dark-theme .pika-table td.is-selected .pika-button {
    background: #ffb74d;
    color: #000;
}

Такой подход важен для:

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

Градиентные и визуально сложные состояния

Выбранная дата не ограничивается плоским цветом. Pikaday позволяет полностью переопределять визуальный стиль:

.pika-table td.is-selected .pika-button {
    background: linear-gradient(135deg, #4a90e2, #2d6cdf);
    color: #ffffff;
    border-radius: 50%;
}

Расширенные техники:

  • круглая форма (calendar-like UI)
  • мягкие тени:
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
  • эффект “плавающей кнопки”

Изоляция выбранной даты от disabled состояния

Хотя логически выбранная дата не может быть is-disabled, при кастомных конфигурациях или динамическом обновлении возможно пересечение состояний.

Защитная стратегия:

.pika-table td.is-selected.is-disabled .pika-button {
    background: #cccccc;
    color: #666666;
}

Либо полный запрет визуального выделения:

.pika-table td.is-disabled .pika-button {
    pointer-events: none;
}

Анимация смены выбранной даты

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

.pika-table td.is-selected .pika-button {
    animation: sel ect-pop 120ms ease-out;
}

@keyframes select-pop {
    fr om {
        transform: scale(0.85);
        opacity: 0.6;
    }
    to {
        transform: scale(1);
        opacity: 1;
    }
}

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


Кастомные стратегии отображения выбранной даты

В сложных интерфейсах выделение может быть расширено дополнительными элементами:

Индикатор точки

.pika-table td.is-selected .pika-button::after {
    content: '';
    position: absolute;
    bottom: 4px;
    width: 4px;
    height: 4px;
    background: #ffffff;
    border-radius: 50%;
}

Обводка вместо заливки

.pika-table td.is-selected .pika-button {
    background: transparent;
    border: 2px solid #2d6cdf;
    color: #2d6cdf;
}

Инверсия текста

.pika-table td.is-selected .pika-button {
    background: #000;
    color: #fff;
}

Влияние кастомного рендера на стили выбранной даты

Pikaday позволяет переопределять отображение через onRender и onDraw, что влияет на структуру классов.

При кастомном рендере важно:

  • сохранять класс is-selected
  • не удалять базовую структуру td > button
  • учитывать повторную генерацию DOM при каждом открытии

Иначе стили выбранной даты перестают применяться.


Иерархия приоритетов CSS для выбранной даты

Корректная модель приоритетов выглядит так:

  1. is-selected (базовое состояние выбора)
  2. is-selected + is-today (совмещённое состояние)
  3. is-selected:hover
  4. is-selected:focus
  5. тема (.dark-theme, .custom-theme)
  6. глобальные стили .pika-button

Нарушение этой иерархии приводит к визуальной нестабильности интерфейса.


Поведение при программной смене даты

При вызове метода setDate календарь полностью пересчитывает состояние:

picker.setDate('2026-06-02');

Это приводит к:

  • снятию is-selected со старого элемента
  • добавлению is-selected новому элементу
  • перерисовке DOM-структуры

Поэтому любые анимации должны быть привязаны к CSS-состояниям, а не к JavaScript-событиям напрямую.


Практическая модель устойчивого оформления

Стабильная стилизация выбранной даты строится на трёх принципах:

  • строгая привязка к is-selected
  • контроль конфликтов с is-today
  • изоляция через темы
.pika-table td.is-selected .pika-button {
    background: #2d6cdf;
    color: #fff;
    border-radius: 6px;
    transition: background 150ms ease;
}

.pika-table td.is-selected.is-today .pika-button {
    background: #1f4fa3;
}

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