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

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

Каждый экземпляр Choices.js при инициализации генерирует DOM-структуру с набором классов, основанных на методологии BEM-подобного подхода. Это обеспечивает возможность точечного переопределения внешнего вида отдельных частей компонента: контейнера, списка, элементов выбора, состояния активности и ошибок.


Базовая структура CSS в Choices.js

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

  • .choices — основной контейнер компонента
  • .choices__inner — внутренний блок с полем ввода и выбранными элементами
  • .choices__list — общий класс для списков
  • .choices__list--single — список для одиночного выбора
  • .choices__list--multiple — список для множественного выбора
  • .choices__item — элемент списка
  • .choices__item--selectable — доступный для выбора элемент
  • .is-open — состояние раскрытого dropdown
  • .is-focused — состояние фокуса
  • .is-disabled — отключённое состояние

Ключевой принцип кастомизации заключается в том, что все состояния уже отражены через классы, а значит визуальное поведение полностью контролируется CSS.


Подходы к созданию кастомной темы

Существует два основных подхода к созданию кастомной темы:

  1. Полное переопределение базовых стилей
  2. Наследование с точечным изменением переменных и классов

Первый подход используется при создании уникального UI, второй — при адаптации под существующую дизайн-систему.


Полное переопределение стилей

Полное переопределение предполагает, что стили Choices.js либо отключаются, либо перекрываются с более высокой специфичностью.

Пример базовой обёртки:

.choices {
  font-family: Inter, sans-serif;
  font-size: 14px;
  width: 100%;
}

В этом случае переопределяется базовый контейнер, а дальше строится вся визуальная система.


Стилизация внутреннего контейнера

Внутренний блок .choices__inner отвечает за визуальное оформление поля ввода и выбранных элементов.

.choices__inner {
  background-color: #111827;
  border: 1px solid #374151;
  border-radius: 10px;
  padding: 8px 12px;
  min-height: 42px;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

Часто именно здесь формируется основная «форма» компонента: скругления, отступы, фон и тени.


Состояния взаимодействия

Состояния являются ключевым элементом кастомной темы, так как они определяют поведение UI в реальном времени.

Фокус

.choices.is-focused .choices__inner {
  border-color: #60a5fa;
  box-shadow: 0 0 0 3px rgba(96, 165, 250, 0.3);
}

Открытый список

.choices.is-open .choices__list--dropdown {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

Отключённое состояние

.choices.is-disabled .choices__inner {
  background-color: #1f2937;
  opacity: 0.6;
  cursor: not-allowed;
}

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


Стилизация dropdown списка

Выпадающий список — один из наиболее сложных элементов для кастомизации, так как он требует управления слоями, анимациями и прокруткой.

.choices__list--dropdown {
  background: #111827;
  border: 1px solid #374151;
  border-radius: 10px;
  margin-top: 8px;
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 0.2s ease, transform 0.2s ease;
  z-index: 10;
}

Важно учитывать z-index, особенно если компонент используется внутри модальных окон или сложных layout-сеток.


Элементы списка

Каждый элемент внутри dropdown имеет класс .choices__item. Именно здесь формируется поведение hover и selection.

.choices__item--selectable {
  padding: 8px 10px;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.choices__item--selectable.is-highlighted {
  background-color: #1f2937;
}

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


Множественный выбор и теги

В режиме multiple Choices.js превращается в систему тегов, где каждый выбранный элемент отображается как отдельный блок.

.choices__list--multiple .choices__item {
  background-color: #2563eb;
  border: none;
  border-radius: 6px;
  color: #ffffff;
  padding: 4px 8px;
  margin-right: 6px;
  margin-bottom: 4px;
}

Кнопка удаления элемента:

.choices__item--selectable .choices__button {
  margin-left: 6px;
  border-left: 1px solid rgba(255, 255, 255, 0.2);
  padding-left: 6px;
  cursor: pointer;
}

Важно учитывать компактность тегов, особенно при большом количестве выбранных значений.


Кастомизация input-поля

Поле ввода внутри Choices.js имеет отдельный стиль, который часто требует адаптации под дизайн системы.

.choices__input {
  background: transparent;
  border: none;
  outline: none;
  color: #e5e7eb;
  font-size: 14px;
  padding: 4px;
}

Для тёмных тем важно правильно управлять цветом текста и placeholder.

.choices__input::placeholder {
  color: #9ca3af;
}

Работа с анимациями

Анимации в кастомной теме должны быть согласованы с общей системой интерфейса. Основные параметры:

  • скорость раскрытия dropdown
  • плавность появления элементов
  • поведение при закрытии

Пример универсального transition:

.choices__list--dropdown {
  transition: opacity 0.25s ease, transform 0.25s ease;
}

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


Интеграция с дизайн-системой

При интеграции Choices.js в существующую дизайн-систему важно синхронизировать:

  • цветовую палитру
  • радиусы скруглений
  • тени и elevation
  • размеры элементов

Пример привязки к CSS-переменным:

:root {
  --bg-primary: #0f172a;
  --border-default: #334155;
  --text-primary: #e2e8f0;
  --accent: #3b82f6;
}

.choices__inner {
  background: var(--bg-primary);
  border-color: var(--border-default);
  color: var(--text-primary);
}

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


Адаптивность кастомной темы

Choices.js должен корректно работать на разных экранах, особенно в мобильных интерфейсах.

@media (max-width: 640px) {
  .choices__inner {
    padding: 6px 10px;
    font-size: 13px;
  }

  .choices__list--dropdown {
    border-radius: 8px;
  }
}

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


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

При создании кастомной темы часто возникают конфликты со стандартными стилями библиотеки. Решение зависит от уровня контроля:

  • использование более специфичных селекторов
  • подключение кастомного CSS после библиотеки
  • применение !important как крайняя мера

Пример повышения специфичности:

form .choices .choices__inner {
  border-width: 2px;
}

Использование !important допустимо только при невозможности иного решения.


Оптимизация визуальной нагрузки

При большом количестве компонентов на странице важно минимизировать:

  • количество теней
  • сложные градиенты
  • глубокие анимации

Лёгкая тема обычно использует:

  • плоские цвета
  • минимальные transition
  • ограниченную палитру состояний

Это снижает нагрузку на рендеринг и улучшает отзывчивость интерфейса.