Back

Стилизация элементов Select с помощью современного CSS

Стилизация элементов Select с помощью современного CSS

Элемент <select> всегда был одним из самых трудно стилизуемых элементов форм. В отличие от полей ввода или кнопок, он исторически рендерился с использованием UI-компонентов уровня операционной системы, что означало, что CSS мог затронуть только поверхность. Это ограничение подталкивало разработчиков к обходным путям, которые до сих пор распространены в production-коде.

Эта статья охватывает оба подхода: широко поддерживаемую устаревшую технику с использованием appearance: none и новую модель appearance: base-select, которая в настоящее время появляется в современных браузерах на базе Chromium.

Ключевые выводы

  • Нативные элементы <select> сопротивляются стилизации, потому что браузеры исторически делегируют их рендеринг операционной системе, что приводит к несогласованным результатам на разных платформах.
  • Техника appearance: none в сочетании с элементом-обёрткой и кастомной стрелкой через clip-path является наиболее надёжным кроссбраузерным методом для стилизации закрытого состояния select.
  • appearance: base-select (Chrome/Edge 135+) открывает возможности стилизации для выпадающей панели, иконки стрелки, галочек и выбранного содержимого — но пока только в браузерах на базе Chromium.
  • Используйте @supports (appearance: base-select) для наслоения современного подхода в качестве прогрессивного улучшения поверх устаревшей базовой версии.

Почему нативные элементы <select> сопротивляются CSS-стилизации

Браузеры традиционно передавали рендеринг <select> операционной системе. Результатом были несогласованные размеры блоков, рендеринг шрифтов и стили выпадающих стрелок в Chrome, Firefox, Safari и Edge, без надёжного способа унифицировать их только через CSS.

Открытый выпадающий список (панель опций) остаётся в значительной степени нестилизуемым в большинстве браузеров даже сегодня. Это жёсткое ограничение, которое стоит иметь в виду перед выбором подхода.

Устаревший подход: appearance: none с элементом-обёрткой

Наиболее широко поддерживаемая техника CSS-стилизации элементов select включает три шага:

  1. Убрать нативное оформление с помощью appearance: none.
  2. Обернуть <select> в контейнерный элемент, который можно свободно стилизовать.
  3. Добавить кастомную выпадающую стрелку с использованием clip-path или фонового SVG.
:root {
  --select-border: #777;
  --select-arrow: var(--select-border);
}

select {
  appearance: none;
  background-color: transparent;
  border: none;
  padding: 0 1em 0 0;
  width: 100%;
  font-family: inherit;
  font-size: inherit;
  cursor: inherit;
  line-height: inherit;
  outline: none;
}

.select {
  display: grid;
  grid-template-areas: "select";
  align-items: center;
  position: relative;
  border: 1px solid var(--select-border);
  border-radius: 0.25em;
  padding: 0.25em 0.5em;
  background-color: #fff;
}

select,
.select::after {
  grid-area: select;
}

.select::after {
  content: "";
  width: 0.8em;
  height: 0.5em;
  background-color: var(--select-arrow);
  clip-path: polygon(100% 0%, 0 0%, 50% 100%);
  justify-self: end;
  pointer-events: none;
}

Трюк с наложением CSS-сетки здесь стоит понять: назначение и <select>, и псевдоэлементу ::after одной и той же именованной области сетки накладывает их друг на друга, позволяя кастомной стрелке визуально находиться сверху без нарушения поведения клика нативного контрола.

Для состояний фокуса, поскольку outline на нативном select не ведёт себя надёжно во всех браузерах, распространённое решение — добавить соседний элемент <span class="focus"> и нацелиться на него с помощью select:focus + .focus, используя position: absolute для отрисовки видимого кольца фокуса.

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

Современный подход: appearance: base-select

Chrome 135 и Edge 135 представили новую opt-in модель, которая открывает внутренние части <select> для прямой CSS-стилизации. Вы активируете её так:

select,
select::picker(select) {
  appearance: base-select;
}

Это открывает несколько новых целей для стилизации:

  • ::picker(select) — выпадающая панель, содержащая опции
  • ::picker-icon — индикатор выпадающей стрелки
  • option::checkmark — галочка, показываемая рядом с выбранной опцией
  • :open — псевдокласс, активный пока picker открыт
  • option:checked — нацеливается на текущую выбранную опцию

С base-select вы можете стилизовать выпадающий picker напрямую, анимировать его открытие и закрытие, и использовать элемент <selectedcontent> для зеркалирования содержимого выбранной опции в закрытый контрол. Поддерживающие браузеры также позволяют более богатую разметку внутри опций, когда включена модель настраиваемого select.

Поддержка браузерами: в настоящее время ограничена в основном браузерами на базе Chromium. Проверьте текущий статус на Can I Use.

Используйте @supports для применения в качестве прогрессивного улучшения:

@supports (appearance: base-select) {
  select,
  select::picker(select) {
    appearance: base-select;
  }
}

Какой подход следует использовать?

appearance: noneappearance: base-select
Поддержка браузерами95%+Ограниченная (см. таблицу поддержки)
Стилизует выпадающую панельНетДа
Богатое содержимое в опцияхНетДа
ДоступностьНативнаяНативная

Используйте технику обёртки с appearance: none в качестве базовой. Она работает везде, сохраняет доступность и даёт вам надёжный контроль над закрытым состоянием select. Наслаивайте appearance: base-select поверх с помощью @supports для браузеров, которые это поддерживают.

Заключение

Кастомизация HTML-выпадающих списков select с помощью CSS больше не является выбором между “полным контролем с JavaScript” или “принятием браузерных настроек по умолчанию”. Паттерн обёртки с appearance: none остаётся надёжной кроссбраузерной основой, в то время как appearance: base-select открывает дверь к стилизации выпадающей панели, встраиванию более богатого содержимого в опции и анимации picker. Разрыв между этими двумя крайностями сокращается, просто пока не равномерно во всех браузерах. Начните с устаревшей техники, прогрессивно наслаивайте современную, и вы охватите самый широкий круг пользователей с наименьшим трением.

Часто задаваемые вопросы

Нет. Установка appearance: none только убирает визуальную стилизацию, предоставляемую операционной системой. Базовый HTML-элемент select сохраняет всё нативное поведение клавиатуры, включая навигацию клавишами со стрелками, Enter и Space для открытия выпадающего списка, и Tab для перемещения фокуса. Программы чтения с экрана продолжают корректно объявлять опции, потому что структура DOM не изменена.

Поддержка настраиваемых элементов select всё ещё развивается и варьируется в зависимости от браузера. Браузеры на базе Chromium первыми внедрили эту функцию, в то время как другие движки всё ещё реализуют её. Проверьте последние данные о совместимости на caniuse.com перед тем, как полагаться на неё в production, и оберните ваши стили base-select внутрь блока @supports (appearance: base-select), чтобы неподдерживающие браузеры корректно откатывались к вашим устаревшим стилям.

Элемент select игнорирует многие CSS-свойства при нативном рендеринге. Обёрточный div даёт вам полный контроль над границами, border-radius, цветом фона и кастомной стрелкой через псевдоэлемент. Техника наложения сетки накладывает стрелку поверх select без вмешательства в события клика, чего вы не можете достичь только на самом select.

Используйте CSS-псевдоэлемент на обёртке с clip-path для отрисовки формы треугольника чисто на CSS. Установите pointer-events: none на псевдоэлементе, чтобы клики проходили через него к select внизу. Альтернативно, вы можете использовать встроенный SVG в качестве background-image на обёртке, закодированный как data URI, чтобы избежать дополнительного сетевого запроса.

Truly understand users experience

See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..

OpenReplay