Когда речь заходит о кастомизации полей формы, наибольшую сложность представляет стилизация HTML-элемента select
. В этом случае разработчики часто обращаются за библиотекой или фреймворком, в которых не всегда удачно и в полном объёме воспроизводится вся функциональность нативного элемента управления.
Если не брать во внимание суждения о ценности элементов управления select
или подобных им, можно констатировать факт: полностью воссоздать их функции, учесть все нюансы поведения и сохранить доступность для людей с ограниченными возможностями – гиперсложная задача.
Ниже будет показано, что и как можно сделать с внешним видом select
с помощью обычного CSS, оставаясь в рамках требований WCAG к доступности (читаемость, контрастность, пользовательские настройки), а также вариантов написания: справа-налево и слева-направо.
Основные стили
Сперва сбросим параметры текста.
select {
font: inherit;
letter-spacing: inherit;
word-spacing: inherit;
}
font
Свойство font
наследует все стили от контейнера(ов). Иногда при сбросе CSS указывают размер шрифта font-size
, но в этом нет необходимости. font
будет наследовать стили всех своих параметров: font-size
, font-family
, font-style
, font-variant
, font-weight
, font-stretch
и font-height
(если установлено). Ещё он добавляет высоту строки line-height
. В-общем, шрифт будет адаптироваться к изменениям, которые касаются всей страницы, либо с помощью надстроек, либо через настройки браузера/системы.
letter-spacing
Если пользователь (или автор) изменяет параметры текста, чтобы повлиять на расстояние между буквами, это не будет касаться предустановленных для поля значений. Наследование параметров font
не повлияет на межбуквенное расстояние, поэтому нужно явно указать необходимость наследования значения letter-spacing: inherit
. Это поможет соответствовать требованиям WCAG 2.1 Success Criterion 1.4.12: Text Spacing
word-spacing
Аналогично межбуквенному letter-spacing
, значение word-spacing
для управления интервалами между словами не будет наследоваться, если это не объявить явным образом. WCAG 1.4.12 применяется и для расстояния между словами.
line-height
Обратите внимание, что в коде не устанавливается высота строки line-height
. Это значение нормально наследуется вместе с остальными параметрами шрифта в свойстве font
. Если обнаружится, что это не так (например, из-за явной установки высоты строки ) можно добавить line-height: inherit
, чтобы соответствовать WCAG 1.4.12.
Пример
В этом примере демонстрируется применение этого минимального набора стилей.
Как настроить стрелку для select
Часто, стрелка (индикатор того, что это выпадашка – поле выбора значений) по умолчанию плохо вписывается в дизайн и её лучше заменить на что-нибудь более подходящее. Вот необходимый минимум стилей, с помощью которых можно заменить стрелку у select
:
select {
font: inherit;
letter-spacing: inherit;
word-spacing: inherit;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
}
select:not([multiple]) {
padding-right: 1.2em;
background-repeat: no-repeat;
background-position: calc(100% - 0.25em) 0.35em;
background-size: 0.85em auto;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80'%3E%3Cpath d='M70.3 13.8L40 66.3 9.7 13.8z' fill='%23000'%3E%3C/path%3E%3C/svg%3E");
}
/* скроет иконку стрелки в IE */
select::-ms-expand {
display: none;
}
Здесь удаляются стили, устанавливаемые браузером, освобождается место для графической стрелки, а затем новая картинка стрелки вставляется в качестве фона. Это должно применяться только в том случае, если select
обычный и предназначен для выбора одиночного значения, а не нескольких (multiple
).
Этот пример демонстрирует замену стрелки по умолчанию элементу select
.
Продолжение настройки select
Стоит обратить внимание, что интервалы у текста не очень хороши. Потенциально можно сделать их более привлекательными, удобными и доступными для пользователей с помощью всего нескольких дополнительных стилей. Например, можно настроить border
и padding
. Эти два свойства расширяют базовые стили, описанные выше, чтобы сделать текстовые поля более удобными.
select {
font: inherit;
letter-spacing: inherit;
word-spacing: inherit;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
/* рамка и отступы */
border: 0.1em solid;
padding: 0 0.2em;
}
border
Изменение значений CSS-свойств для рамки поля сопряжено с риском. Согласно WCAG (SC 1.4.11: Non-text Contrast), если для элемента формы не вносить изменений в стили по умолчанию, то это никак не повлияет на контрастность. Тем не менее, с помощью border: 0.1em solid
будет установлена толщина рамки на основе размера шрифта. Теперь рамка поля выбора будет масштабироваться вместе с текстом. Заодно она становится толще, чем используется по умолчанию в большинстве браузеров.
Здесь умышленно не установлен цвет рамки, чтобы позволить браузеру сделать это самостоятельно. Конечно, если фон страницы не белый, можно изменить цвет рамки.
padding
Трогать padding
для select
не обязательно. Однако, содержимое поля будет немного легче читать и использовать, если немного его настроить. Это поможет сделать отступы в select
ближе к аналогичным в textarea
и input
, если их тоже предстоит настраивать.
Стилизация состояний select
Поля формы могут находиться в разных состояниях. Отключенное, сфокусированное, с ошибкой и обязательное – это наиболее распространенные состояния, которые можно применить к элементам управления. Не обязательно применять какие-либо из предлагаемых стилей, но можно использовать селекторы и логику, лежащие в их основе, чтобы реализовать состояния в собственной библиотеке шаблонов.
Отключено disabled
Отключенные поля исключаются из требований к контрастности WCAG, как и элементы управления интерфейса по умолчанию. Если ничего не делать, браузер самостоятельно сделает всё необходимое. Поэтому здесь не стоит что-то менять в настройках цвета фона поля или текста, достаточно позволить браузеру выполнить эту работу по его усмотрению.
Сфокусировано focused
WCAG SC 2.4.7 не рекомендует здесь ничего делать, согласно Technique G149, потому что браузер добавляет свой собственный стиль для фокуса. Тем не менее, можно сделать его ещё более очевидным, например, использовать синий контур с хорошим контрастом к белому и добавить тень:
select:focus {
outline: 0.15em solid #00f;
box-shadow: 0 0 0.2em #00f;
}
Только для чтения readonly
Нативный элемент <select>
не поддерживает атрибут readonly
.
Обязательное поле required
Пока label
указывает, что поле обязательное (вместе с атрибутом required
), нет большой необходимости стилизовать select
как-то особенно. Но, например, можно увеличить обязательному полю толщину границы слева. В совокупности с оформлением других полей это может дать достаточно информации. Можно не менять цвет рамки, позволяя наследование (по умолчанию от стилей пользовательского агента).
select[required] {
border-left-width: 0.3em;
}
Поле с ошибками
Одной красной рамки тут будет недостаточно (из-за сбоев WCAG по контрасту и только по цвету), а массивные тени могут испачкать всю страницу. Слишком много усилий по привлечению внимания к ошибкам создают шум, требующий от пользователей больших усилий для их устранения. Вместо этого можно добавить небольшой индикатор в углу поля. Градиент, образующий красную метку, устанавливает белый цвет фона поля. Обратите внимание, здесь в первый раз полю select
явно задаётся цвет фона.
Здесь не будет использоваться селектор :invalid
, потому что он может негативно влиять на нативное представление ошибок в браузере. Вместо этого можно использовать наличие-отсутствие aria-invalid
, не просто переключая его с true
на false
, а добавляя или удаляя этот атрибут. Поскольку стрелка, как было решено выше, также является фоновым изображением, её здесь придётся повторно установить, если речь об обычном select
без множественного выбора (multiple
).
select[aria-invalid] {
background: linear-gradient(
135deg,
rgba(255, 0, 0, 1) 0,
rgba(255, 0, 0, 1) 0.4em,
rgba(255, 255, 255, 0) 0.4em
);
}
select[aria-invalid]:not([multiple]) {
background-repeat: no-repeat, no-repeat;
background-position: 0 0, calc(100% - 0.25em) 0.35em;
background-size: 0.85em auto;
background-image: linear-gradient(
135deg,
rgba(255, 0, 0, 1) 0,
rgba(255, 0, 0, 1) 0.4em,
rgba(255, 255, 255, 0) 0.4em
),
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80'%3E%3Cpath d='M70.3 13.8L40 66.3 9.7 13.8z' fill='%23000'%3E%3C/path%3E%3C/svg%3E");
}
Стили для интернационализации
Чтобы не сильно усложнять, здесь речь пойдёт только о стилях написания справа налево, а при необходимости, будет не трудно разобраться и адаптировать это.
Для нативного поля выбора select
достаточно поправить только стили, которые написаны, исходя из ожиданий для языков с написанием слева направо, а именно: стрелка, индикаторы обязательности и ошибки, которые позиционируются в зависимости от того, с какой стороны пользователь начинает читать. Здесь достаточно переместить стрелку, красную метку и более толстую границу на противоположную сторону.
*[dir="rtl"] select:not([multiple]) {
padding-right: 0.2em;
padding-left: 1.2em;
background-position: 0.25em 0.35em;
}
*[dir="rtl"] select[required] {
border-left-width: 0.1em;
border-right-width: 0.3em;
}
*[dir="rtl"] select[aria-invalid] {
background: linear-gradient(
225deg,
rgba(255, 0, 0, 1) 0,
rgba(255, 0, 0, 1) 0.4em,
rgba(255, 255, 255, 0) 0.4em
);
}
*[dir="rtl"] select[aria-invalid]:not([multiple]) {
background: linear-gradient(
225deg,
rgba(255, 0, 0, 1) 0,
rgba(255, 0, 0, 1) 0.4em,
rgba(255, 255, 255, 0) 0.4em
),
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80'%3E%3Cpath d='M70.3 13.8L40 66.3 9.7 13.8z' fill='%23000'%3E%3C/path%3E%3C/svg%3E");
background-repeat: no-repeat;
background-size: auto, 0.85em auto;
background-position: 0 0, 0.25em 0.35em;
}
Стили режима высокой контрастности Windows
Поскольку используются нативные элементы управления, нет вмешательства в цвета и стили для критически важных функций, которые отсутствуют в WHCM, т.е. в основном были применены системные стили – в этом направлении особо ничего делать не нужно.
Стиль подсветки контура outline
здесь хорошо адаптируется. Переключение в disabled
работает, как и должно по умолчанию. Стили border
не затрагивают цвет и не повлияют работу с любой контрастностью.
Единственное, что может теряться – это индикация ошибки. При таком небольшом количестве цветов (система WHCM) может понадобиться акцент на другом визуальном индикаторе ошибок. Например, использовать label
, чтобы четко указать на ошибки.
Стили для печати
Толщина границы масштабируется в зависимости от размера шрифта – это можно игнорировать. Пользователь, скорее всего, выберет размер шрифта, который будет разборчивым. Фоном отключенных полей и полей с ошибками можно управлять в настройках печати. Размер текста для поля не изменялся, наследуется. Здесь ничего не надо делать.
Стили для тёмного режима (dark mode)
Тёмный режим – это функциональный запрос, который нужно создать для поддержки стилей. Здесь не будет примера, а только рекомендации. Достаточно выбрать цвет фона и цвет шрифта и не писать все новые стили с нуля.
Следует наследовать цвет текста и фон (или сделать его прозрачным) и выбрать цвет рамки, который по-прежнему соответствует требованиям контрастности. Стили состояния при фокусировке тоже нуждаются в достаточном контрасте. Метка для состояния при ошибке зависит от фонового градиента к белому, поэтому нужно будет полностью переопределить стили ошибок, в том числе для RTL. Отключенные (disabled
) поля также потребуют некоторой работы, так как явно заданы цвета границ и текста.
Заключение
Пример стилизованного select
в разных состояниях с сохранением WCAG-доступности.
Когда речь идет о стилизации полей формы, нужно обратить внимание на минимальный набор стилей, который понадобится, чтобы обеспечить соответствие общему дизайну и поддержку состояний, которые перечислены выше.
Похожие публикации, посвященные стилизации HTML-элемента select
: Select Like It’s 2019 и Custom Select Styles with Pure CSS немного отличаются подходами, но заслуживают не меньшего внимания. Может быть эти варианты даже лучше соответствуют вашим целям и требованиям.