Choices.js формирует интерфейс вокруг нативных элементов
<select> и <input>, заменяя их на
кастомную структуру DOM с набором предсказуемых классов состояний.
Стилизация этих состояний строится не на глубокой модификации HTML, а на
работе с классами, которые библиотека динамически добавляет в ответ на
действия пользователя и изменения данных.
Ключевая особенность архитектуры — разделение визуальных состояний и логики. Библиотека не требует переопределения поведения элементов, а предоставляет набор CSS-хуков:
.is-focused.is-open.is-disabled.is-active.is-highlighted.is-selected.is-flipped.has-valueЭти классы становятся основой для построения интерфейсных состояний без необходимости вмешиваться в JavaScript-логику.
Фокус — одно из центральных состояний компонента, определяющее визуальную активность поля ввода или контейнера.
В Choices.js фокус обычно отражается через класс
.is-focused, который добавляется к корневому контейнеру
.choices.
Структурно это выглядит так:
<div class="choices is-focused">
<div class="choices__inner">
<input class="choices__input">
</div>
</div>
Стилизация фокуса должна учитывать не только визуальное выделение, но и контекст взаимодействия пользователя.
.choices.is-focused .choices__inner {
border-color: #2684ff;
box-shadow: 0 0 0 3px rgba(38, 132, 255, 0.2);
}
.choices.is-focused .choices__input {
caret-color: #2684ff;
}
Фокус часто комбинируется с hover-состояниями, поэтому важно избегать конфликтующих визуальных эффектов. В приоритете всегда должен быть фокус, так как он отражает активное управление с клавиатуры.
Открытие списка опций управляется классом .is-open. Он
добавляется к корневому контейнеру и активирует отображение
dropdown-блока .choices__list--dropdown.
DOM-структура при открытии:
<div class="choices is-open">
<div class="choices__inner"></div>
<div class="choices__list choices__list--dropdown is-active"></div>
</div>
Основные аспекты стилизации:
.choices__list--dropdown {
opacity: 0;
transform: translateY(-6px);
pointer-events: none;
transition: all 0.2s ease;
}
.choices.is-open .choices__list--dropdown {
opacity: 1;
transform: translateY(0);
pointer-events: auto;
}
Для более сложных интерфейсов часто применяется изменение скруглений контейнера при открытии:
.choices.is-open .choices__inner {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
Это позволяет визуально «склеить» поле ввода и список опций в единый компонент.
Отключённое состояние формируется через .is-disabled.
Оно блокирует взаимодействие и изменяет визуальное восприятие
элемента.
<div class="choices is-disabled">
<select disabled></select>
</div>
Основная задача стилизации — передать неактивность без потери читаемости.
.choices.is-disabled .choices__inner {
background-color: #f5f5f5;
border-color: #ddd;
color: #999;
cursor: not-allowed;
}
.choices.is-disabled .choices__input {
cursor: not-allowed;
}
Важно учитывать, что disabled состояние распространяется на весь компонент, включая элементы выбора и удаления тегов в multi-select.
При работе с выпадающим списком Choices.js использует класс
.is-highlighted, который обозначает текущий элемент под
курсором или клавиатурной навигацией.
<div class="choices__item choices__item--choice is-highlighted">
Option 1
</div>
Стилизация этого состояния критична для доступности интерфейса.
.choices__item--choice.is-highlighted {
background-color: #2684ff;
color: #fff;
}
При проектировании интерфейса важно избегать слишком слабого контраста, так как highlighted-элемент часто используется при навигации стрелками.
В single-select выбранное значение отображается в
.choices__item--selectable, а в multi-select дополнительно
формируются теги .choices__item--choice.
Для выбранных элементов применяется класс
.is-selected.
<div class="choices__item is-selected">
Option 2
</div>
Стилизация:
.choices__item.is-selected {
font-weight: 500;
background-color: #e6f0ff;
}
В multi-select выбранные элементы отображаются как отдельные блоки:
<div class="choices__list--multiple">
<div class="choices__item choices__item--selectable">
Tag 1
</div>
</div>
Их стилизация часто включает:
.choices__item--selectable {
background-color: #f1f3f5;
border-radius: 16px;
padding: 4px 10px;
}
.choices__item--selectable .choices__button {
margin-left: 6px;
}
Класс .has-value используется для определения
заполненности поля. Он добавляется к контейнеру, когда пользователь
выбрал значение или ввёл текст.
<div class="choices has-value">
Это состояние часто используется для:
.choices.has-value .choices__placeholder {
opacity: 0;
}
В более сложных интерфейсах .has-value применяется как
триггер для плавающих меток:
.choices.has-value + label {
transform: translateY(-18px);
font-size: 12px;
}
Choices.js автоматически определяет доступное пространство и может
добавлять класс .is-flipped, если dropdown отображается
вверх.
<div class="choices is-open is-flipped">
Это состояние требует отдельного контроля позиционирования:
.choices.is-flipped .choices__list--dropdown {
top: auto;
bottom: 100%;
transform-origin: bottom;
}
При стилизации важно учитывать, что анимации должны зеркально отражаться:
.choices.is-flipped .choices__list--dropdown {
transform: translateY(6px);
}
.choices.is-open.is-flipped .choices__list--dropdown {
transform: translateY(0);
}
Хотя Choices.js не добавляет отдельные классы для hover, он
полагается на CSS-псевдокласс :hover внутри структуры
элементов.
.choices__item--choice:hover {
background-color: #f0f6ff;
}
Однако важно учитывать взаимодействие hover и keyboard navigation.
При наличии .is-highlighted hover должен уступать
приоритет.
.choices__item--choice.is-highlighted,
.choices__item--choice:hover {
background-color: #2684ff;
color: #fff;
}
В более строгих интерфейсах hover можно отключать при активной клавиатурной навигации через дополнительный класс состояния:
.choices.is-focused .choices__item--choice:hover {
background-color: transparent;
}
Choices.js не предоставляет встроенной системы ошибок, но хорошо
интегрируется с внешними валидаторами. Обычно к контейнеру добавляется
кастомный класс, например .has-error.
<div class="choices has-error">
Стилизация ошибок строится на визуальном акценте:
.choices.has-error .choices__inner {
border-color: #e53935;
box-shadow: 0 0 0 3px rgba(229, 57, 53, 0.15);
}
Дополнительно можно стилизовать сообщения:
.choices__error-message {
color: #e53935;
font-size: 12px;
margin-top: 4px;
}
Реальные интерфейсы редко находятся в одном состоянии. Choices.js позволяет комбинировать классы, и именно это определяет сложность стилизации.
Примеры комбинаций:
.is-focused.is-open.is-disabled.has-value.is-flipped.is-open.has-error.is-focusedПриоритеты состояний должны быть заранее определены:
Пример приоритетной логики в CSS:
.choices.is-disabled .choices__inner {
pointer-events: none;
opacity: 0.6;
}
.choices.has-error .choices__inner {
border-color: #e53935;
}
.choices.is-focused .choices__inner {
border-color: #2684ff;
}
Плавные переходы между состояниями повышают восприятие интерфейса. Choices.js хорошо работает с CSS transitions, особенно для:
.choices__inner {
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.choices__list--dropdown {
transition: opacity 0.2s ease, transform 0.2s ease;
}
Важно избегать анимации layout-свойств вроде height,
если компонент используется в динамических формах, чтобы не создавать
скачков интерфейса.
Multi-select добавляет дополнительный слой состояний для тегов:
.choices__item--selectable:hover {
background-color: #e9ecef;
}
.choices__button {
opacity: 0.6;
transition: opacity 0.2s ease;
}
.choices__button:hover {
opacity: 1;
}
При удалении элемента часто используется визуальная обратная связь:
.choices__item--selectable.is-deleting {
opacity: 0;
transform: scale(0.9);
transition: all 0.15s ease;
}