В основе визуального оформления Awesomplete лежит комбинация заранее заданной HTML-структуры и набора CSS-классов, которые библиотека добавляет динамически. Вся система темизации строится вокруг переопределения этих классов без необходимости вмешательства в логику JavaScript, что делает внешний вид полностью отделённым от поведения.
Ключевой элемент архитектуры — минималистичная DOM-структура:
awesompleteulliactive, selectedmark
для подсветки совпаденийИменно эти классы становятся точками входа для любой кастомной темы.
Awesomplete использует фиксированный набор классов, которые можно считать контрактом между логикой и внешним видом:
.awesomplete {
position: relative;
display: inline-block;
}
.awesomplete > ul {
position: absolute;
left: 0;
z-index: 1000;
min-width: 100%;
list-style: none;
margin: 0;
padding: 0;
}
.awesomplete > ul > li {
padding: 8px 12px;
cursor: pointer;
}
Состояние активного элемента:
.awesomplete > ul > li[aria-selected="true"],
.awesomplete > ul > li.active {
background: #2684ff;
color: #fff;
}
Подсветка совпадений:
.awesomplete mark {
background: transparent;
font-weight: 600;
}
Смысл темизации заключается в полном переопределении этих базовых правил.
Существует несколько устойчивых подходов к созданию кастомного оформления:
Каждый подход влияет на масштабируемость и предсказуемость внешнего вида.
Наиболее устойчивый метод — добавление собственного класса к контейнеру:
<input class="awesomplete theme-dark" />
Дальнейшее стилизование строится вокруг пространства имён:
.theme-dark.awesomplete > ul {
background: #1e1e1e;
color: #eaeaea;
border: 1px solid #333;
border-radius: 6px;
}
.theme-dark.awesomplete > ul > li {
padding: 10px 14px;
}
.theme-dark.awesomplete > ul > li:hover {
background: #333;
}
Такой подход исключает конфликт с другими инстансами компонента и позволяет использовать несколько тем одновременно.
CSS-переменные позволяют отделить цветовую схему от структуры стилей:
.awesomplete {
--bg: #ffffff;
--text: #222;
--hover: #f2f2f2;
--active: #2684ff;
}
.awesomplete > ul {
background: var(--bg);
color: var(--text);
}
.awesomplete > ul > li:hover {
background: var(--hover);
}
.awesomplete > ul > li.active {
background: var(--active);
color: #fff;
}
Изменение темы сводится к переопределению переменных:
.theme-dark {
--bg: #1b1b1b;
--text: #e0e0e0;
--hover: #2a2a2a;
--active: #4c8dff;
}
Состояние навигации по списку играет ключевую роль в UX, поэтому его оформление обычно выделяется отдельно:
.awesomplete > ul > li.active {
transform: translateX(2px);
transition: all 0.15s ease;
}
Дополнительные визуальные индикаторы:
.awesomplete > ul > li.active::before {
content: "";
position: absolute;
left: 0;
width: 3px;
height: 100%;
background: #2684ff;
}
Такой приём создаёт акцент без изменения структуры DOM.
Awesomplete автоматически оборачивает совпавшие фрагменты в тег
mark. Это позволяет полностью контролировать акцентирование
текста:
.awesomplete mark {
background: none;
color: inherit;
border-bottom: 2px solid #ffcc00;
}
Альтернативный вариант с более агрессивным выделением:
.awesomplete mark {
background: #fff3a0;
padding: 0 2px;
border-radius: 2px;
}
Различные сценарии интерфейса требуют разных плотностей отображения.
Компактный вариант:
.theme-compact.awesomplete > ul > li {
padding: 4px 8px;
font-size: 13px;
}
Расширенный вариант:
.theme-spacious.awesomplete > ul > li {
padding: 14px 18px;
font-size: 16px;
}
Регулировка плотности часто важнее цветовой схемы в интерфейсах с высокой частотой ввода.
Темы могут включать дополнительную структуру внутри элементов списка:
.awesomplete .subtitle {
display: block;
font-size: 12px;
opacity: 0.6;
}
HTML-структура при кастомном рендеринге:
<li>
Основной текст
<span class="subtitle">дополнительное описание</span>
</li>
Такая иерархия особенно полезна при автодополнении с API-данными.
Плавное появление списка улучшает восприятие интерфейса:
.awesomplete > ul {
opacity: 0;
transform: translateY(4px);
transition: opacity 0.15s ease, transform 0.15s ease;
}
.awesomplete[aria-expanded="true"] > ul {
opacity: 1;
transform: translateY(0);
}
Дополнительная анимация элементов:
.awesomplete > ul > li {
transition: background 0.1s ease, padding-left 0.1s ease;
}
.awesomplete > ul > li:hover {
padding-left: 16px;
}
Расширение темы часто включает добавление декоративных элементов:
.awesomplete > ul > li::before {
content: "›";
margin-right: 8px;
opacity: 0.5;
}
Или использование SVG-фона:
.awesomplete > ul > li {
background-image: url("icon.svg");
background-repeat: no-repeat;
background-position: 8px center;
padding-left: 32px;
}
Awesomplete активно использует ARIA-атрибуты, которые также могут участвовать в стилизации:
.awesomplete > ul[hidden] {
display: none;
}
.awesomplete > ul[aria-hidden="true"] {
opacity: 0;
}
Состояние фокуса:
.awesomplete input:focus {
outline: 2px solid #2684ff;
outline-offset: 2px;
}
В отдельных случаях базовая стилизация полностью отключается:
.awesomplete > ul {
all: unset;
position: absolute;
width: 100%;
}
Далее строится полностью новая визуальная система поверх минимальной структуры:
.awesomplete > ul > li {
display: flex;
justify-content: space-between;
padding: 10px;
background: #fff;
border-bottom: 1px solid #eee;
}
Такой подход применяется при интеграции в сложные дизайн-системы.
Темизация может зависеть от окружения компонента:
.form-dark .awesomplete > ul {
background: #111;
color: #ddd;
}
.form-light .awesomplete > ul {
background: #fff;
color: #111;
}
Контекстный подход позволяет использовать один и тот же компонент в разных разделах интерфейса без модификации JavaScript.
Некоторые стили зависят от динамического состояния списка:
.awesomplete[aria-expanded="true"] input {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
Или визуальная связь с количеством элементов:
.awesomplete > ul:empty {
display: none;
}
Такие правила усиливают связь между логикой и визуальной реакцией интерфейса без вмешательства в код библиотеки.