Когда речь заходит о кастомизации полей формы, наибольшую сложность представляет стилизация 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.
Пример
В этом примере демонстрируется применение этого минимального набора стилей.
See this code Простой Select on x.xhtml.ru.
Как настроить стрелку для 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
).
See this code Select с измененной стрелкой on x.xhtml.ru.
Этот пример демонстрирует замену стрелки по умолчанию элементу 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-доступности.
See this code Select Menus on x.xhtml.ru.
Когда речь идет о стилизации полей формы, нужно обратить внимание на минимальный набор стилей, который понадобится, чтобы обеспечить соответствие общему дизайну и поддержку состояний, которые перечислены выше.
Похожие публикации, посвященные стилизации HTML-элемента select
: Select Like It’s 2019 и Custom Select Styles with Pure CSS немного отличаются подходами, но заслуживают не меньшего внимания. Может быть эти варианты даже лучше соответствуют вашим целям и требованиям.
Under-Engineered Select Menus.
I have a list of countries, some with a very long name:
<select name=countries>
<option value=af>Afghanistan</option>
<option value=ax>Åland Islands</option>
...
<option value=gs>South Georgia and the South Sandwich Islands</option>
...
</select>
By default, the select box would be as long as the longest option in the list. I want to create a select box such that it exhibits the default behaviour when viewed from a wide browser window, but fit in nicely to 90% of container width when viewed from a narrow browser window, smaller than the length of the longest option.
I tried min-width: 90%;
, but it didn’t work. Can this be done by CSS styling alone?
asked May 20, 2012 at 7:32
Question OverflowQuestion Overflow
10.7k18 gold badges71 silver badges109 bronze badges
5
USE style="max-width:90%;"
<select name=countries style="max-width:90%;">
<option value=af>Afghanistan</option>
<option value=ax>Åland Islands</option>
...
<option value=gs>South Georgia and the South Sandwich Islands</option>
...
</select>
LIVE DEMO
answered May 20, 2012 at 7:42
Krishanu DeyKrishanu Dey
6,2726 gold badges50 silver badges69 bronze badges
10
You’ve simply got it backwards. Specifying a minimum width would make the select menu always be at least that width, so it will continue expanding to 90% no matter what the window size is, also being at least the size of its longest option.
You need to use max-width
instead. This way, it will let the select menu expand to its longest option, but if that expands past your set maximum of 90% width, crunch it down to that width.
answered May 20, 2012 at 7:56
animuson♦animuson
53.2k28 gold badges142 silver badges147 bronze badges
8
Add div wrapper
<div id=myForm>
<select name=countries>
<option value=af>Afghanistan</option>
<option value=ax>Åland Islands</option>
...
<option value=gs>South Georgia and the South Sandwich Islands</option>
...
</select>
</div>
and then write CSS
#myForm select {
width:200px; }
#myForm select:focus {
width:auto; }
Hope this will help.
answered Nov 15, 2017 at 14:00
The <select>
HTML element represents a control that provides a menu of options.
Try it
The above example shows typical <select>
usage. It is given an id
attribute to enable it to be associated with a <label>
for accessibility purposes, as well as a name
attribute to represent the name of the associated data point submitted to the server. Each menu option is defined by an <option>
element nested inside the <select>
.
Each <option>
element should have a value
attribute containing the data value to submit to the server when that option is selected. If no value
attribute is included, the value defaults to the text contained inside the element. You can include a selected
attribute on an <option>
element to make it selected by default when the page first loads.
The <select>
element has some unique attributes you can use to control it, such as multiple
to specify whether multiple options can be selected, and size
to specify how many options should be shown at once. It also accepts most of the general form input attributes such as required
, disabled
, autofocus
, etc.
You can further nest <option>
elements inside <optgroup>
elements to create separate groups of options inside the dropdown.
For further examples, see The native form widgets: Drop-down content.
Attributes
This element includes the global attributes.
autocomplete
-
A string providing a hint for a user agent’s autocomplete feature. See The HTML autocomplete attribute for a complete list of values and details on how to use autocomplete.
autofocus
-
This Boolean attribute lets you specify that a form control should have input focus when the page loads. Only one form element in a document can have the
autofocus
attribute. disabled
-
This Boolean attribute indicates that the user cannot interact with the control. If this attribute is not specified, the control inherits its setting from the containing element, for example
<fieldset>
; if there is no containing element with thedisabled
attribute set, then the control is enabled. form
-
The
<form>
element to associate the<select>
with (its form owner). The value of this attribute must be theid
of a<form>
in the same document. (If this attribute is not set, the<select>
is associated with its ancestor<form>
element, if any.)This attribute lets you associate
<select>
elements to<form>
s anywhere in the document, not just inside a<form>
. It can also override an ancestor<form>
element. multiple
-
This Boolean attribute indicates that multiple options can be selected in the list. If it is not specified, then only one option can be selected at a time. When
multiple
is specified, most browsers will show a scrolling list box instead of a single line dropdown. name
-
This attribute is used to specify the name of the control.
required
-
A Boolean attribute indicating that an option with a non-empty string value must be selected.
size
-
If the control is presented as a scrolling list box (e.g. when
multiple
is specified), this attribute represents the number of rows in the list that should be visible at one time. Browsers are not required to present a select element as a scrolled list box. The default value is0
.Note: According to the HTML specification, the default value for size should be
1
; however, in practice, this has been found to break some websites, and no other browser currently does that, so Mozilla has opted to continue to return0
for the time being with Firefox.
Usage notes
Selecting multiple options
On a desktop computer, there are a number of ways to select multiple options in a <select>
element with a multiple
attribute:
Mouse users can hold the Ctrl, Command, or Shift keys (depending on what makes sense for your operating system) and then click multiple options to select/deselect them.
Warning: The mechanism for selecting multiple non-contiguous items via the keyboard described below currently only seems to work in Firefox.
On macOS, the Ctrl + Up and Ctrl + Down shortcuts conflict with the OS default shortcuts for Mission Control and Application windows, so you’ll have to turn these off before it will work.
Keyboard users can select multiple contiguous items by:
-
Focusing on the
<select>
element (e.g. using
Tab
). -
Selecting an item at the top or bottom of the range they want to select using the
Up
and
Down
cursor keys to go up and down the options. -
Holding down the
Shift
key and then using the
Up
and
Down
cursor keys to increase or decrease the range of items selected.
Keyboard users can select multiple non-contiguous items by:
-
Focusing on the
<select>
element (e.g. using
Tab
). -
Holding down the
Ctrl
key then using the
Up
and
Down
cursor keys to change the «focused» select option, i.e. the one that will be selected if you choose to do so. The «focused» select option is highlighted with a dotted outline, in the same way as a keyboard-focused link. -
Pressing
Space
to select/deselect «focused» select options.
Styling with CSS
The <select>
element is notoriously difficult to style productively with CSS. You can affect certain aspects like any element — for example, manipulating the box model, the displayed font, etc., and you can use the appearance
property to remove the default system appearance
.
However, these properties don’t produce a consistent result across browsers, and it is hard to do things like line different types of form element up with one another in a column. The <select>
element’s internal structure is complex, and hard to control. If you want to get full control, you should consider using a library with good facilities for styling form widgets, or try rolling your own dropdown menu using non-semantic elements, JavaScript, and WAI-ARIA to provide semantics.
For more useful information on styling <select>
, see:
- Styling HTML forms
- Advanced styling for HTML forms
Also see the «Customizing select styles» example below for an example of you could attempt a simple <select>
styling.
Examples
Basic select
The following example creates a very simple dropdown menu, the second option of which is selected by default.
<!-- The second value will be selected initially -->
<select name="choice">
<option value="first">First Value</option>
<option value="second" selected>Second Value</option>
<option value="third">Third Value</option>
</select>
Advanced select with multiple features
The follow example is more complex, showing off more features you can use on a <select>
element:
<label>Please choose one or more pets:
<select name="pets" multiple size="4">
<optgroup label="4-legged pets">
<option value="dog">Dog</option>
<option value="cat">Cat</option>
<option value="hamster" disabled>Hamster</option>
</optgroup>
<optgroup label="Flying pets">
<option value="parrot">Parrot</option>
<option value="macaw">Macaw</option>
<option value="albatross">Albatross</option>
</optgroup>
</select>
</label>
You’ll see that:
- Multiple options are selectable because we’ve included the
multiple
attribute. - The
size
attribute causes only 4 lines to display at a time; you can scroll to view all the options. - We’ve included
<optgroup>
elements to divide the options up into different groups. This is a purely visual grouping, its visualization generally consists of the group name being bolded, and the options being indented. - The «Hamster» option includes a
disabled
attribute and therefore can’t be selected at all.
Customizing select styles
This example shows how you could use some CSS and JavaScript to provide extensive custom styling for a <select>
box.
This example basically:
- Clones the
<select>
‘s context (the<option>
s) in a parent wrapper and reimplements the standard expected behavior using additional HTML elements and JavaScript. This includes basic tab behavior to provide keyboard accessibility. - Maps some standards native
attributes
todata-attributes
of the new elements in order to manage state and CSS.
Note: Not all native features are supported, it’s a Proof of Concept. IT starts from standard HTML but the same results can be achieved starting from JSON data, custom HTML, or other solutions.
HTML
<form>
<fieldset>
<legend>Standard controls</legend>
<select name="1A" id="select" autocomplete="off" required>
<option>Carrots</option>
<option>Peas</option>
<option>Beans</option>
<option>Pneumonoultramicroscopicsilicovolcanoconiosis</option>
</select>
</fieldset>
<fieldset id="custom">
<legend>Custom controls</legend>
<select name="2A" id="select" autocomplete="off" required>
<option>Carrots</option>
<option>Peas</option>
<option>Beans</option>
<option>Pneumonoultramicroscopicsilicovolcanoconiosis</option>
</select>
</fieldset>
</form>
CSS
body {
font-family: Cambria, Cochin, Georgia, Times, "Times New Roman", serif;
}
.select:focus {
border-color: blue;
}
html body form fieldset#custom div.select[data-multiple] div.header {
display: none;
}
html body form fieldset#custom div.select div.header {
content: "↓";
display: flex;
flex: 1;
align-items: center;
padding: 0;
position: relative;
width: auto;
box-sizing: border-box;
border-width: 1px;
border-style: inherit;
border-color: inherit;
border-radius: inherit;
}
html body form fieldset#custom div.select div.header::after {
content: "↓";
align-self: stretch;
display: flex;
align-content: center;
justify-content: center;
justify-items: center;
align-items: center;
padding: 0.5em;
}
html body form fieldset#custom div.select div.header:hover::after {
background-color: blue;
}
.select .header select {
appearance: none;
font-family: inherit;
font-size: inherit;
padding: 0;
border-width: 0;
width: 100%;
flex: 1;
display: none;
}
.select .header select optgroup {
display: none;
}
.select select div.option {
display: none;
}
html body form fieldset#custom div.select {
user-select: none;
box-sizing: border-box;
position: relative;
border-radius: 4px;
border-style: solid;
border-width: 0;
border-color: gray;
width: auto;
display: inline-block;
}
html body form fieldset#custom div.select:focus,
html body form fieldset#custom div.select:hover {
border-color: blue;
}
html body form fieldset#custom div.select[data-open] {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
html body form fieldset#custom div.select[data-open] datalist {
display: initial;
}
html body form fieldset#custom div.select datalist {
appearance: none;
position: absolute;
border-style: solid;
border-width: 1px;
border-color: gray;
left: 0;
display: none;
width: 100%;
box-sizing: border-box;
z-index: 2;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
html body form fieldset#custom div.select datalist div.option {
background-color: white;
margin-bottom: 1px;
cursor: pointer;
padding: 0.5em;
border-width: 0;
}
html body form fieldset#custom div.select datalist div.option:hover,
html body form fieldset#custom div.select datalist div.option:focus,
html body form fieldset#custom div.select datalist div.option:checked {
background-color: blue;
color: white;
}
html
body
form
fieldset#custom
div.select
div.optgroup
div.option[data-disabled] {
color: gray;
}
html
body
form
fieldset#custom
div.select
div.optgroup
div.option[data-checked] {
background-color: blue;
color: white;
}
html body form fieldset#custom div.select div.optgroup div.label {
font-weight: bold;
}
html body form fieldset#custom div.select div.optgroup div.option div.label {
font-weight: normal;
padding: 0.25em;
}
html body form fieldset#custom div.select div.header span {
flex: 1;
padding: 0.5em;
}
JavaScript
const selects = custom.querySelectorAll('select');
for (const select of selects) {
const div = document.createElement('div');
const header = document.createElement('div');
const datalist = document.createElement('datalist');
const optgroups = select.querySelectorAll('optgroup');
const span = document.createElement('span');
const options = select.options;
const parent = select.parentElement;
const multiple = select.hasAttribute('multiple');
function onclick(e) {
const disabled = this.hasAttribute('data-disabled');
select.value = this.dataset.value;
span.innerText = this.dataset.label;
if (disabled) return;
if (multiple) {
if (e.shiftKey) {
const checked = this.hasAttribute("data-checked");
if (checked) {
this.removeAttribute("data-checked");
} else {
this.setAttribute("data-checked", "");
}
} else {
const options = div.querySelectorAll('.option');
for (let i = 0; i < options.length; i++) {
const option = options[i];
option.removeAttribute("data-checked");
}
this.setAttribute("data-checked", "");
}
}
}
function onkeyup(e) {
e.preventDefault();
e.stopPropagation();
if (e.keyCode === 13) {
this.click();
}
}
div.classList.add('select');
header.classList.add('header');
div.tabIndex = 1;
select.tabIndex = -1;
span.innerText = select.label;
header.appendChild(span);
for (const attribute of select.attributes) {
div.dataset[attribute.name] = attribute.value;
}
for (let i = 0; i < options.length; i++) {
const option = document.createElement('div');
const label = document.createElement('div');
const o = options[i];
for (const attribute of o.attributes) {
option.dataset[attribute.name] = attribute.value;
}
option.classList.add('option');
label.classList.add('label');
label.innerText = o.label;
option.dataset.value = o.value;
option.dataset.label = o.label;
option.onclick = onclick;
option.onkeyup = onkeyup;
option.tabIndex = i + 1;
option.appendChild(label);
datalist.appendChild(option);
}
div.appendChild(header);
for (const o of optgroups) {
const optgroup = document.createElement('div');
const label = document.createElement('div');
const options = o.querySelectorAll('option');
Object.assign(optgroup, o);
optgroup.classList.add('optgroup');
label.classList.add('label');
label.innerText = o.label;
optgroup.appendChild(label);
div.appendChild(optgroup);
for (const o of options) {
const option = document.createElement('div');
const label = document.createElement('div');
for (const attribute of o.attributes) {
option.dataset[attribute.name] = attribute.value;
}
option.classList.add('option');
label.classList.add('label');
label.innerText = o.label;
option.tabIndex = i + 1;
option.dataset.value = o.value;
option.dataset.label = o.label;
option.onclick = onclick;
option.onkeyup = onkeyup;
option.tabIndex = i + 1;
option.appendChild(label);
optgroup.appendChild(option);
}
}
div.onclick = (e) => {
e.preventDefault();
};
parent.insertBefore(div, select);
header.appendChild(select);
div.appendChild(datalist);
datalist.style.top = `${header.offsetTop + header.offsetHeight}px`;
div.onclick = (e) => {
if (!multiple) {
const open = this.hasAttribute("data-open");
e.stopPropagation();
if (open) {
div.removeAttribute("data-open");
} else {
div.setAttribute("data-open", "");
}
}
};
div.onkeyup = (event) => {
event.preventDefault();
if (event.keyCode === 13) {
div.click();
}
};
document.addEventListener('click', (e) => {
if (div.hasAttribute("data-open")) {
div.removeAttribute("data-open");
}
});
const width = Math.max(...Array.from(options).map((e) => {
span.innerText = e.label;
return div.offsetWidth;
}));
console.log(width);
div.style.width = `${width}px`;
}
document.forms[0].onsubmit = (e) => {
const data = new FormData(this);
e.preventDefault();
submit.innerText = JSON.stringify([...data.entries()]);
};
Result
Technical summary
Content categories |
Flow content, phrasing content, interactive content, listed, labelable, resettable, and submittable form-associated element |
---|---|
Permitted content |
Zero or more <option> or<optgroup> elements.
|
Tag omission | None, both the starting and ending tag are mandatory. |
Permitted parents |
Any element that accepts phrasing content. |
Implicit ARIA role |
combobox with nomultiple attribute and nosize attribute greater than 1, otherwiselistbox
|
Permitted ARIA roles |
menu with nomultiple attribute and nosize attribute greater than 1, otherwise norole permitted
|
DOM interface | HTMLSelectElement |
Specifications
Specification |
---|
HTML Standard # the-select-element |
Browser compatibility
BCD tables only load in the browser
See also
- Events fired by
<select>
:change
,input
- The
<option>
element - The
<optgroup>
element
<!DOCTYPE html>
<
html
lang
=
"en"
>
<
head
>
<
meta
charset
=
"UTF-8"
>
<
meta
name
=
"viewport"
content
=
"width=device-width, initial-scale=1.0"
>
<
title
>Pure CSS Styled Select</
title
>
<
style
>
body {
background-color: #a4ecae;
font-family: 'Source Sans Pro', sans-serif;
}
.demo {
margin: 100px auto;
}
.dropdown-container {
width: 250px;
margin: 100px auto;
position: relative;
}
select {
width: 100%;
height: 50px;
font-size: 100%;
font-weight: bold;
cursor: pointer;
border-radius: 0;
background-color: #2bd325;
border: none;
border-bottom: 2px solid #37c40c;
color: white;
appearance: none;
padding: 10px;
padding-right: 38px;
-webkit-appearance: none;
-moz-appearance: none;
transition: color 0.3s ease, background-color 0.3s ease,
border-bottom-color 0.3s ease;
}
/* For IE <= 11 */
select::-ms-expand {
display: none;
}
.select-icon {
position: absolute;
top: 4px;
right: 4px;
width: 30px;
height: 36px;
pointer-events: none;
border: 2px solid #70d82a;
padding-left: 5px;
transition: background-color 0.3s ease, border-color 0.3s ease;
}
.select-icon svg.icon {
transition: fill 0.3s ease;
fill: white;
}
select:hover,
select:focus {
color: #5ac02b;
background-color: white;
border-bottom-color: #141313;
}
select:hover ~ .select-icon,
select:focus ~ .select-icon {
background-color: white;
border-color: #3dd13db6;
}
select:hover ~ .select-icon svg.icon,
select:focus ~ .select-icon svg.icon {
fill: #67c02b;
}
</
style
>
</
head
>
<
body
>
<
div
class
=
"demo"
>
<
div
class
=
"dropdown-container"
>
<
select
class
=
"slct"
>
<
option
value
=
"1"
>GFG</
option
>
<
option
value
=
"2"
>OS
</
option
>
<
option
value
=
"3"
>DBMS</
option
>
<
option
value
=
"4"
>
Data Structure
</
option
>
</
select
>
<
div
class
=
"select-icon"
>
<
svg
focusable
=
"false"
viewBox
=
"0 0 104 128"
width
=
"25"
height
=
"35"
class
=
"icon"
>
<
path
d="m2e1 95a9 9 0 0 1 -9 9 9 9 0 0 1 -9 -9 9 9
0 0 1 9 -9 9 9 0 0 1 9 9zm0-3e1a9 9 0 0 1
-9 9 9 9 0 0 1 -9 -9 9 9 0 0 1 9 -9 9 9 0 0
1 9 9zm0-3e1a9 9 0 0 1 -9 9 9 9 0 0 1 -9 -9 9
9 0 0 1 9 -9 9 9 0 0 1 9 9zm14
55h68v1e1h-68zm0-3e1h68v1e1h-68zm0-3e1h68v1e1h-68z">
</
path
>
</
svg
>
</
div
>
</
div
>
</
div
>
</
body
>
my selectbox is showing scroll when number of options are more than 20 i just want to show scrol in when options are more than 10
<select>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
<option>9</option>
<option>10</option>
<option>11</option>
</select>
asked May 8, 2014 at 6:35
5
Try adding this to the <select>
element:
onfocus='this.size=10;'
onblur='this.size=1;'
onchange='this.size=1; this.blur();
like:
<select onfocus='this.size=10;' onblur='this.size=1;'
onchange='this.size=1; this.blur();'>
SAMPLE DEMO
John
12.3k12 gold badges94 silver badges163 bronze badges
answered May 8, 2014 at 6:41
reuelabreuelab
1,9761 gold badge18 silver badges28 bronze badges
3
Seriously guys, there is a size attribute for the select
element:
<select size="10">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
<option>9</option>
<option>10</option>
<option>11</option>
</select>
FIDDLE: http://jsfiddle.net/UR46N/
John
12.3k12 gold badges94 silver badges163 bronze badges
answered May 8, 2014 at 6:46
Vince CVince C
8586 silver badges16 bronze badges
1
In Case of setting size (height/width) and fitting the selection list in the pop up then try the following in VFPage- Salesforce:
<apex:selectList onclick="this.size=5;" required="true" id="form-element-05" value="{!scheduleBatchWrapper.hour}" size="1" styleClass="slds-select selectObj slds-m-left_medium slds-m-top_medium schTime" style="max-width:50%; margin-bottom:5% margin-top:5%,max-height:20%" >
<apex:selectOptions value="{!scheduleBatchWrapper.hoursList}"></apex:selectOptions>
</apex:selectList>
// here onclick=»this.size=5;» will set the size to 5 when you click on the selectList.
//it works fine for Chrome,Firefox,Edge.
Thanks
answered May 27, 2020 at 12:22
As much as I see, none of the former answers explain the Options box.
As much as I know, we don’t have accessibility to manipulate options in a select box.
We just can change the colors and background color at the same time, add a new font and that’s all we could do.
If we add padding or margin to the Options, the drop-down list will be still the same as its initial condition.
The only way to do so is to design a select-box on your own( by using radio buttons, prevent their default style, and add a background color to it. )
answered Apr 27, 2021 at 11:13
<select>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
option {
padding: 5px 0;
}
answered Feb 1, 2020 at 7:42
1
I am using Bootstrap and this answer helped me.
.dropdown-menu {
max-height: 280px;
overflow-y: auto;
}
answered Oct 27, 2021 at 9:46
AnupamAnupam
14.6k18 gold badges66 silver badges93 bronze badges
1
use below css
select{ padding:5px;}
answered May 8, 2014 at 6:41
AmitAmit
1,81119 silver badges36 bronze badges
my selectbox is showing scroll when number of options are more than 20 i just want to show scrol in when options are more than 10
<select>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
<option>9</option>
<option>10</option>
<option>11</option>
</select>
asked May 8, 2014 at 6:35
5
Try adding this to the <select>
element:
onfocus='this.size=10;'
onblur='this.size=1;'
onchange='this.size=1; this.blur();
like:
<select onfocus='this.size=10;' onblur='this.size=1;'
onchange='this.size=1; this.blur();'>
SAMPLE DEMO
John
12.3k12 gold badges94 silver badges163 bronze badges
answered May 8, 2014 at 6:41
reuelabreuelab
1,9761 gold badge18 silver badges28 bronze badges
3
Seriously guys, there is a size attribute for the select
element:
<select size="10">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
<option>9</option>
<option>10</option>
<option>11</option>
</select>
FIDDLE: http://jsfiddle.net/UR46N/
John
12.3k12 gold badges94 silver badges163 bronze badges
answered May 8, 2014 at 6:46
Vince CVince C
8586 silver badges16 bronze badges
1
In Case of setting size (height/width) and fitting the selection list in the pop up then try the following in VFPage- Salesforce:
<apex:selectList onclick="this.size=5;" required="true" id="form-element-05" value="{!scheduleBatchWrapper.hour}" size="1" styleClass="slds-select selectObj slds-m-left_medium slds-m-top_medium schTime" style="max-width:50%; margin-bottom:5% margin-top:5%,max-height:20%" >
<apex:selectOptions value="{!scheduleBatchWrapper.hoursList}"></apex:selectOptions>
</apex:selectList>
// here onclick=»this.size=5;» will set the size to 5 when you click on the selectList.
//it works fine for Chrome,Firefox,Edge.
Thanks
answered May 27, 2020 at 12:22
As much as I see, none of the former answers explain the Options box.
As much as I know, we don’t have accessibility to manipulate options in a select box.
We just can change the colors and background color at the same time, add a new font and that’s all we could do.
If we add padding or margin to the Options, the drop-down list will be still the same as its initial condition.
The only way to do so is to design a select-box on your own( by using radio buttons, prevent their default style, and add a background color to it. )
answered Apr 27, 2021 at 11:13
<select>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
option {
padding: 5px 0;
}
answered Feb 1, 2020 at 7:42
1
I am using Bootstrap and this answer helped me.
.dropdown-menu {
max-height: 280px;
overflow-y: auto;
}
answered Oct 27, 2021 at 9:46
AnupamAnupam
14.6k18 gold badges66 silver badges93 bronze badges
1
use below css
select{ padding:5px;}
answered May 8, 2014 at 6:41
AmitAmit
1,81119 silver badges36 bronze badges
Время прочтения
4 мин
Просмотры 88K
Как-то вечером я убивал время, читая статьи в интернете, и наткнулся на вот этот хабропост пользователя Cyapa, где расписано, как кастомизировать select на чистом css. В процессе просмотра данного решения нашел несколько весьма неудобных моментов, которые постарался исправить в своем решении этой задачи. Итак, приступим.
Пока смотрел код того поста, заметил, что автор сделал селект, который невозможно закрыть при клике вне его, а также невозможность открыть селект при клике на название элемента, если оно уже выбрано.
В своем варианте кастомизации я, так же как и предыдущий автор, использовал label, input[type=«radio»] и мощь css-селекторов. Так как сам селект средствами css полностью кастомизировать нереально, я имитировал поведение селекта.
Для начала, я накидал вот такую разметку:
Показать html код
<!-- Лейбел, при клике на который открывается селект -->
<label for="select" class="select">
<!-- Этот инпут отвечает за закрытие селекта при клике за его пределами. Также этот инпут является стандартным значением нашего селекта -->
<input type="radio" name="list" value="not_changed" id="bg" checked />
<!-- Этот инпут является переключателем селекта в состояние "открыт" -->
<input type="radio" name="list" value="not_changed" id="select">
<!-- Этот лейбел используется для создания подложки, клик по которой приводит к закрытию селекта -->
<label class="bg" for="bg"></label>
<!-- Этот див - список параметров селекта, где #text - то, что выводится, когда ничего не выбрано -->
<div class="items">
<!-- Инпут, при клике на который происходит выбор параметра и сворачивание селекта -->
<input type="radio" name="list" value="first_value" id="list[0]">
<!-- Название параметра -->
<label for="list[0]">First option</label>
<!-- Инпут, при клике на который происходит выбор параметра и сворачивание селекта[1] -->
<input type="radio" name="list" value="second_value" id="list[1]">
<!-- Инпут, при клике на который происходит выбор параметра и сворачивание селекта[1] -->
<label for="list[1]">Second loooooong option</label>
<!-- Текст селекта по умолчанию. Выводится тогда, когда ничего не выбрано -->
<span id="text">Select something...</span>
</div>
</label>
При просмотре данного кода у вас мог возникнуть вопрос: «Почему у всех инпутов одинаковое имя?». Отвечу сразу: это сделано для того, чтобы наш селект адекватно вел себя(открывался и закрывался тогда, когда нужно). Но обо всем по порядку. Давайте перейдем к самой интересной, на мой взгляд, части — css.
Показать css код
/* скрываем все инпуты, чтобы все выглядело красиво */
input
{
display: none;
}
/* стилизуем стандартный текст лейбела(желательно смотреть этот стиль после .items) */
#text
{
position: absolute;
display: block;
top: 0;
padding-left: 10px;
}
/* Задаем параметры нашего селекта - ширину, высоту и line-height(для центрирования текста по вертикали;этот парметр меньше ширины на 4px, т.к. в нашем блоке есть border размером в 2px со всех сторон) */
.select
{
display: inline-block;
width: 160px;
height: 34px;
line-height: 30px;
position: relative;
}
/* Это наша стрелочка, показывающая, что селект можно раскрыть */
.select:before
{
content: ">";
display: inline-block;
background: white;
position: absolute;
right: -5px;
top: 2px;
z-index: 2;
width: 30px;
height: 26px;
text-align: center;
line-height: 26px;
border: 2px solid #ddd;
transform: rotate(90deg);
cursor: pointer;
}
/* Если ничего не выбрано, то наш изначальный текст черного цвета, как и должно быть */
.select input[name="list"]:not(:checked) ~ #text
{
color: black;
background: white;
}
/* Если же что-то выбрано, то наш текст становится невидимым и встает сверху выбранного параметра, чтобы при клике на него можно было заного открыть селект, что не было реализовано прошлым автором */
.select input[name="list"]:checked ~ #text
{
background: transparent;
color: transparent;
z-index: 2;
}
/* Стилизация выключенного селекта */
#select:disabled ~ .items #text
{
background: #eee;
}
/* Стилизация блока с опциями. min-height сделана для фикса высоты при абсолютном позиционировании, overflow же сделан для фиксированной высоты(см. ниже) */
.items
{
display: block;
min-height: 30px;
position: absolute;
border: 2px solid #ddd;
overflow: hidden;
width: 160px;
cursor: pointer;
}
/* Если наш селект закрыт, то он имеет высоту 30px(сделано для того, чтобы слишком большие надписи не растягивали его в высоту) */
#select:not(:checked) ~ .items
{
height: 30px;
}
/* Все лейбелы(названия опций) изначально скрыты */
.items label
{
border-top: 2px solid #ddd;
display: none;
padding-left: 10px;
background: white;
}
/* Тут много объяснять не надо - просто выделение при наведении */
.items label:hover
{
background: #eee;
cursor: pointer;
}
/* Опять же фикс из-за абсолютного позиционирования */
#select:checked ~ .items
{
padding-top: 30px;
}
/* Если наш селект открыт, то надо сделать все опции видимыми */
#select:checked ~ .items label
{
display: block;
}
/* Если какая-либо опция была выбрана, то сделать ее видимой(при выборе селект автоматически закроется) */
.items input:checked + label
{
display: block!important;
border: none;
background: white;
}
/* При открытии селекта создать подложку во весь экран, при клике на которую селект закроется, а значение останется пустым. background сделан для наглядности */
#select:checked ~ .bg
{
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 0;
background: rgba(0,0,0,0.4);
}
Вот она — самая интересная часть, в которой надо осмыслить как смена выбора инпута (все инпуты с типом радио имеют одинаковое имя => мы можем выбрать только один из них) влияет на наш селект. Еще одной особенностью этого варианта является возможность отключить селект, используя атрибут disabled на #select.
Готовый пример вы можете найти здесь.
Вот, собственно, и все. Парочка минусов предыдущего автора пофикшены, так что это решение, полагаю, на данный момент можно считать идеальным css-вариантом селекта. Надеюсь, мое решение кому-нибудь пригодится.
HTML тег <select> используется для определения выпадающего списка, который появляется при нажатии мышью на элемент формы и позволяет пользователю выбрать один из вариантов.
Для определения доступных вариантов выбора используется тег <option>, вложенный в тег <select>.
По умолчанию первый пункт в списке отображается как выбранный. Для изменения предопределенного варианта используется атрибут selected.
Для объединения нескольких вариантов в одну группу используется тег <optgroup>. Содержимое тега <optgroup> выглядит как заголовок жирного начертания.
Внешний вид списка зависит от использования атрибута size, который устанавливает высоту списка. Ширина списка зависит от длины текста в теге <option>. Ширину можно также задать с помощью CSS стилей.
Если необходимо отправлять данные на сервер, либо обращаться к списку через скрипты, то тег <select> необходимо поместить внутрь формы (тег <form>).
Содержимое элемента заключается между открывающим (<select>) и закрывающим (</select>) тегами. Закрывающий тег обязателен
Пример
<!DOCTYPE html>
<html>
<head>
<title>Заголовок окна веб-страницы</title>
</head>
<body>
<form action="action_form.php" target="_top">
<select>
<option value="books">Книги</option>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="php">PHP</option>
<option value="js">JavaScript</option>
</select>
</form>
</body>
</html>
Результат
Пример
<!DOCTYPE html>
<html>
<head>
<title>Заголовок окна веб-страницы</title>
</head>
<body>
<select>
<optgroup label="Книги">
<option value="html">HTML</option>
<option value="css">CSS</option>
</optgroup>
<optgroup label="Сниппеты">
<option value="git">Git</option>
<option value="java">Java</option>
</optgroup>
</select>
</body>
</html>
В этом примере мы использовали тег <optgroup> для сбора опций в группе.
Результат
Пример
<!DOCTYPE html>
<html>
<head>
<title>Заголовок окна веб-страницы</title>
</head>
<body>
<p>Аэропорт вылета:</p>
<form action="action_form.php" target="_top">
<input type = "text" list = "airports" name="airports">
<datalist id = "airports">
<option value = "Санкт-Петербург">
<option value = "Краснодар">
<option value = "Москва">
<option value = "Новосибирск">
</datalist>
<input type = "submit" value = "подтвердить">
</form>
</body>
</html>
Результат
В этом примере мы использовали тег <form>, так как нам необходимо отправить данные на сервер.
Тег <select> поддерживает также глобальные атрибуты и атрибуты событий.