Стилизация select CSS: как оформить поле и стрелку
Стилизация select css начинается со сброса нативного вида через appearance: none. После этого задайте размер, шрифт, рамку и фон, а стрелку добавьте через SVG или обертку. Нативное поле сохраняет клавиатурную навигацию и проверку формы.
- Почему select выглядит по-разному в браузерах
- Как задать размер, шрифт, рамку и фон select
- Как убрать стандартный вид через appearance
- Своя стрелка для select
- Состояния select
- Стилизация option и optgroup
- Множественный выбор: multiple и size
- Настраиваемый select с base-select
- Темная тема для select
- Когда нужен выпадающий список на JavaScript
- Ошибки при стилизации select
- Готовый пример оформления select на HTML и CSS
Почему select выглядит по-разному в браузерах
Закрытый select рисуют браузер и операционная система. Поэтому одинаковые CSS-правила могут дать разные стрелки, рамки и списки.
CSS хорошо меняет размеры, шрифт, цвет, фон, рамку и отступы закрытого поля.
Открытый список и его пункты частично контролируют движок и система. Оформление select с помощью HTML и CSS выравнивает поле в интерфейсе, но не гарантирует одинаковый вид каждого option.
Общие приемы оформления форм описаны в руководстве MDN.
Как задать размер, шрифт, рамку и фон select
Свяжите поле с подписью через одинаковые значения for и id. Такое сочетание помогает пользователю понять назначение элемента.
<label for="topic">Тема</label>
<select id="topic" name="topic" class="select">
<option value="">Выберите тему</option>
<option value="html">HTML</option>
<option value="css">CSS</option>
</select>Соберите базовый вид одним правилом. box-sizing: border-box включает рамку и отступы в расчет размера.
.select {
box-sizing: border-box;
width: 240px;
max-width: 100%;
min-height: 44px;
padding: 8px 12px;
font: inherit;
font-size: 16px;
color: #1f2937;
background-color: #fff;
border: 1px solid #9ca3af;
border-radius: 6px;
}widthзадает ширину поля, аmax-widthудерживает его в контейнере.min-heightсохраняет удобный размер при разном тексте.paddingотделяет текст от рамки и стрелки.font: inheritпередает полю шрифт родительского элемента.background-color,color,borderиborder-radiusменяют внешний вид.
Используйте min-height, если текст может занимать больше места. Фиксированный height требует расчета с учетом padding и рамки.
Мелкий шрифт в iOS Safari может вызвать автоматический зум при фокусе на поле.
В примере для читаемости задан font-size: 16px после наследования шрифта. Не отключайте масштабирование страницы: пользователю может понадобиться увеличить текст самостоятельно.
Как убрать стандартный вид через appearance
Уберите системную стрелку и нативное оформление рамки через appearance: none. Выбор пункта и отправка формы при этом сохраняются.
.select {
appearance: none;
}Для современных браузеров используйте стандартное свойство appearance без вендорных префиксов.
Добавьте собственную стрелку после сброса вида. Рамку, фон и отступы задайте явно, как в базовом примере.
Нужный синтаксис и ограничения свойства описаны в документации MDN об appearance.
Чтобы вернуть системное оформление, удалите правило appearance: none. Поле снова получит стандартную стрелку.
Своя стрелка для select
У обычного select нет надежных псевдоэлементов. Стрелку размещают фоном самого поля или рисуют на соседней обертке.
SVG в background-image
Фоновый SVG занимает место справа. Правый отступ защищает длинный пункт от перекрытия.
.select {
appearance: none;
padding-right: 36px;
background-color: #fff;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%231f2937' stroke-width='2'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 12px center;
}Символ # внутри data-URI записан как %23. Цвет стрелки меняется в значении stroke.
Обертка с псевдоэлементом
Обертка принимает ::after, а select остается интерактивным полем. Нажатие проходит к полю благодаря pointer-events: none у стрелки.
<label for="wrapped-topic">Тема</label>
<div class="select-wrap">
<select id="wrapped-topic" name="topic" class="select">
<option value="html">HTML</option>
<option value="css">CSS</option>
</select>
</div>.select-wrap {
position: relative;
display: inline-block;
width: 240px;
max-width: 100%;
color: #1f2937;
}
.select-wrap .select {
width: 100%;
padding-right: 36px;
background-image: none;
}
.select-wrap::after {
content: "";
position: absolute;
top: 50%;
right: 14px;
width: 8px;
height: 8px;
border-right: 2px solid currentColor;
border-bottom: 2px solid currentColor;
transform: translateY(-70%) rotate(45deg);
pointer-events: none;
}Стрелка наследует цвет обертки через currentColor. Нажатие по значку открывает поле.
Состояния select
Оформите наведение, фокус, недоступность и ошибку обязательного поля. Правила состояний поставьте после базового оформления.
.select:not(:disabled):hover {
border-color: #4b5563;
}
.select:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
}
.select:disabled {
color: #6b7280;
background-color: #f3f4f6;
cursor: not-allowed;
}
.select:required:invalid {
color: #6b7280;
}
.select:user-invalid {
border-color: #dc2626;
}Не удаляйте outline без заметной замены. :focus-visible показывает обводку при клавиатурной навигации.
Пустое значение первого пункта запускает проверку обязательного поля.
<label for="required-topic">Тема, обязательно</label>
<select id="required-topic" name="topic" class="select" required>
<option value="">Выберите тему</option>
<option value="html">HTML</option>
<option value="css">CSS</option>
</select>После выбора значения поле проходит проверку required. Псевдокласс :invalid перестает действовать, и текст получает основной цвет.
Добавьте внешний текст ошибки, чтобы пользователь не зависел только от цвета.
Стилизация option и optgroup
Элемент option дает меньше контроля, чем обычный блок. Движок и операционная система могут игнорировать часть отступов, фона и шрифта.
<label for="technology">Технология</label>
<select id="technology" name="technology" class="select">
<optgroup label="Верстка">
<option value="html">HTML</option>
<option value="css">CSS</option>
</optgroup>
<optgroup label="Программирование">
<option value="js">JavaScript</option>
</optgroup>
</select>Атрибут label подписывает группу, а optgroup нельзя выбрать отдельно. На мобильном устройстве список часто рисует система.
Оформление закрытого поля задавайте самому select: его цвет, фон и шрифт не гарантируют такого же оформления раскрытого списка.
В обычных списках Chrome и Firefox размер шрифта может следовать за font-size поля. Однако правило font не гарантирует применения всей гарнитуры, насыщенности и межстрочного интервала к каждому пункту. Системное меню может использовать собственные параметры текста.
Свойства color и background-color у option могут менять текст и фон в настольных Chrome и Firefox. Результат зависит от операционной системы, а подсветка выбранного пункта может перекрывать авторские цвета.
В обычном списке Safari на macOS не рассчитывайте на произвольные фон и шрифт пунктов. Safari на iOS также использует системный интерфейс выбора, который ограничивает оформление option. Сброс appearance: none у закрытого поля эти ограничения не снимает.
В режиме base-select браузер предоставляет выпадающую часть для CSS-оформления, поэтому пункты можно оформлять вместе с контейнером списка.
| Прием | Chrome | Firefox | Safari на macOS | Safari на iOS |
|---|---|---|---|---|
Свойства обычного option | Цвета и размер шрифта могут применяться; результат зависит от ОС | Цвета и размер шрифта могут применяться; результат зависит от ОС | Ограничены системным оформлением | Ограничены системным оформлением |
appearance: base-select | С версии 135 | — | С версии 27 | С версии 27 |
::picker(select) | С версии 135 | — | С версии 27 | С версии 27 |
::picker-icon | С версии 133 | — | С версии 27 | С версии 27 |
Различия обычного и настраиваемого поля описаны в справке MDN об элементе select. Ограничения пунктов перечислены в справке MDN об option.
Сведения о совместимости расширенного режима также доступны на Can I use.
Множественный выбор: multiple и size
Атрибут multiple разрешает выбрать несколько пунктов, а size задает число видимых строк. В таком поле отдельная стрелка обычно не нужна.
<label for="skills">Технологии</label>
<p id="skills-help">Для отдельных пунктов удерживайте Ctrl или Command.</p>
<select id="skills" name="skills" class="select" multiple size="4" aria-describedby="skills-help">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
<option value="php">PHP</option>
</select>.select[multiple] {
height: auto;
padding: 4px;
background-image: none;
}
.select[multiple] option:checked {
background-color: #dbeafe;
color: #1e3a8a;
}Выбранные строки остаются отмеченными. Системная подсветка может заменить заданные цвета.
Настраиваемый select с base-select
Включите расширенное оформление через appearance: base-select в браузерах с поддержкой этого режима.
Псевдоэлемент ::picker(select) обращается к выпадающей части, а ::picker-icon – к встроенной стрелке. Включите расширенный режим через @supports, сохранив базовый вариант поля.
.select {
appearance: none;
}
@supports (appearance: base-select) and selector(::picker(select)) {
.select:not([multiple]):not([size]),
.select:not([multiple]):not([size])::picker(select) {
appearance: base-select;
}
.select:not([multiple]):not([size]) {
background-image: none;
}
.select:not([multiple]):not([size])::picker(select) {
color: #1f2937;
background-color: #fff;
border: 1px solid #9ca3af;
border-radius: 8px;
padding: 4px;
}
}Браузер без нужной поддержки пропустит блок @supports и сохранит базовые правила. Поэтому пользователь получает рабочее поле с обычной стрелкой или SVG.
Настраиваемый select допускает картинки и дополнительную разметку внутри option.
Например, пункт может содержать изображение и текст в отдельном span. CSS задает им размеры, отступы и взаимное расположение. Каждому пункту оставьте понятный текст и явное значение value для отправки формы.
Элемент selectedcontent показывает копию содержимого выбранного пункта в закрытом поле.
Для собственного оформления выбранного значения поместите selectedcontent внутрь button, первым дочерним элементом select. Браузер обновляет его содержимое при выборе другого пункта. Это позволяет показывать в кнопке ту же картинку и подпись, что в списке.
Такая разметка связана с настраиваемым режимом: обычное системное меню не обязано отображать вложенные изображения и элементы. Условие @supports проверяет CSS-возможности, но само по себе не гарантирует поддержку всех новых HTML-элементов. Для простого запасного варианта сохраняйте текстовые названия пунктов.
Общий синтаксис и примеры разметки приведены в материале MDN о customizable select.
Темная тема для select
Свойство color-scheme сообщает браузеру о светлой и темной палитрах. Переменные меняют фон, текст, рамку и цвет подсказки в одном месте.
:root {
color-scheme: light dark;
--select-bg: #fff;
--select-fg: #1f2937;
--select-border: #9ca3af;
--select-muted: #6b7280;
}
@media (prefers-color-scheme: dark) {
:root {
--select-bg: #1f2937;
--select-fg: #f3f4f6;
--select-border: #9ca3af;
--select-muted: #cbd5e1;
}
}
.select {
color: var(--select-fg);
background-color: var(--select-bg);
border-color: var(--select-border);
}
.select:required:invalid {
color: var(--select-muted);
}Проверьте контраст текста, фокуса и disabled в обеих темах. Для стрелки в data-URI задайте отдельный цвет.
Когда нужен выпадающий список на JavaScript
Нативный select подходит для выбора готовых значений. CSS закрывает задачу размера, рамки, цвета и собственной стрелки.
JavaScript-компонент оправдан для поиска по длинному списку или мультивыбора с тегами.
При замене select вы сами отвечаете за клавиатуру, фокус, роли и состояния. Сохраните связанный label и передавайте выбранное значение в форму. Без этих частей декоративный список сложнее для пользователей вспомогательных технологий.
Ошибки при стилизации select
::afterпрямо на select не дает надежной стрелки. Используйте соседнюю обертку.- Удаленный
outlineскрывает клавиатурный фокус. Оставьте обводку или задайте свою. - Фиксированный
heightвместе с padding может обрезать текст. Используйтеmin-heightиbox-sizing: border-box. - Мелкий шрифт может вызвать зум при фокусе в iOS Safari. Увеличьте размер текста поля, не отключая масштабирование страницы.
- Фоновая стрелка без
padding-rightперекрывает длинный пункт. - SVG-стрелка вместе с
::picker-iconдает два значка. Отключайте фон в расширенном режиме. - Запись
linear-gradient(top, ...)использует устаревший порядок аргументов. Пишитеlinear-gradient(to bottom, ...).
Готовый пример оформления select на HTML и CSS
Пример оформления select на HTML и CSS состоит из двух файлов.
Сохраните первый блок как index.html, а второй – как styles.css. HTML подключает таблицу стилей через элемент link.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Стилизованный select</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<form>
<label for="topic">Тема, обязательно</label>
<select id="topic" name="topic" class="select" required>
<option value="">Выберите тему</option>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
</select>
<button type="submit">Продолжить</button>
</form>
</body>
</html>:root {
color-scheme: light dark;
--page-bg: #fff;
--select-bg: #fff;
--select-fg: #1f2937;
--select-border: #9ca3af;
--select-muted: #6b7280;
--select-focus: #2563eb;
--select-error: #b91c1c;
}
@media (prefers-color-scheme: dark) {
:root {
--page-bg: #111827;
--select-bg: #1f2937;
--select-fg: #f3f4f6;
--select-border: #9ca3af;
--select-muted: #cbd5e1;
--select-focus: #93c5fd;
--select-error: #fca5a5;
}
}
body {
margin: 24px;
font: 16px/1.5 system-ui, sans-serif;
color: var(--select-fg);
background-color: var(--page-bg);
}
label {
display: block;
margin-bottom: 8px;
}
.select {
box-sizing: border-box;
appearance: none;
width: 280px;
max-width: 100%;
min-height: 44px;
padding: 8px 36px 8px 12px;
font: inherit;
font-size: 16px;
color: var(--select-fg);
background-color: var(--select-bg);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%239ca3af' stroke-width='2'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 12px center;
border: 1px solid var(--select-border);
border-radius: 6px;
}
.select:not(:disabled):hover {
border-color: var(--select-fg);
}
.select:focus-visible {
outline: 2px solid var(--select-focus);
outline-offset: 2px;
}
.select:disabled {
color: var(--select-muted);
cursor: not-allowed;
}
.select:required:invalid {
color: var(--select-muted);
}
.select:user-invalid {
border-color: var(--select-error);
}
@supports (appearance: base-select) and selector(::picker(select)) {
.select,
.select::picker(select) {
appearance: base-select;
}
.select {
background-image: none;
}
.select::picker(select) {
color: var(--select-fg);
background-color: var(--select-bg);
border: 1px solid var(--select-border);
border-radius: 8px;
padding: 4px;
}
}Откройте файл в браузере. Поле получит рамку и собственную стрелку, а пустая подсказка не пройдет встроенную проверку формы.
Клавишей Tab переведите фокус на поле и выберите тему. Следующее нажатие Tab переведет фокус к кнопке. Расширенный режим применит стили к выпадающей части там, где он доступен.
Чтобы вернуть системное оформление, удалите правила класса select или строку подключения styles.css.
Перед переносом примера в проект добавьте самый длинный пункт вашего списка. Проверьте, что стрелка не перекрывает текст в обеих темах.
Популярное за неделю
- Как создать сайт самому в 2026: 4 способа + пошаговая инструкция 34 мин чтения
- Лучшие конструкторы для создания сайтов — плюсы, минусы и сравнения 22 мин чтения
- overflow hidden что это и почему обрезка не работает 6 мин чтения
- 50 примеров CSS3‑кнопок с эффектами для сайта 5 мин чтения
- 17 эффектных CSS‑анимаций с готовыми примерами 3 мин чтения
- 19 CSS‑спиннеров и прелоадеров для загрузки 5 мин чтения
Комментарии