OpenUI разрабатывает новый элемент -
<selectmenu>. Он уже более года доступен в Chrome за флагом. Этот элемент должен решить давнюю проблему - невозможность кастомизации нативного <select>. <selectmenu>
<button
slot="button"
behavior="button"
>
<span
behavior="selected-value"
></span>
</button>
<option>Option 1</option>
<option>Option 2</option>
</selectmenu>
В чем проблема? Есть нативный
<select>, который из коробки доступен, работает с формами и т.д. Но поповер с опциями никак не может быть стилизован, потому что находится на уровне ОС и недоступен для CSS. Да и внешняя часть имеет ограничения стилизации. Это приводит к тому, что вместо нативного <select> используются библиотеки, которые можно подогнать под дизайн и сделать консистентно во всех браузерах. Но это лишний js на клиенте, а во многих решениях доступность вообще не проработана. <selectmenu> - это решение. Это встроенный веб-компонент, который использует Shadow DOM для инкапсуляции разметки и логики внутри себя, slots для проброса произвольной разметки в определённые места и CSS Shadow Parts для стилизации некоторых внутренних частей.У
<selectmenu> есть определённая анатомия. Компонент состоит из кнопки, внутри которой элемент с текстом выбранной опции и иконка-треугольник. За кнопкой располагается поповер, куда попадают опции и который рисуется при открытии селекта. По умолчанию <selectmenu> работает как <select>, а именно служит контейнером для элементов <option>, которые могут быть опционально обернуты в <optgroup>.<selectmenu>
<option>Опция 1</option>
<option>Опция 2</option>
<optgroup label="Группа">
<option>Опция 3</option>
<option>Опция 4</option>
</optgroup>
</selectmenu>
Благодаря механизму CSS Shadow Parts мы получаем возможность пробиться внутрь Shadow DOM и стилизовать некоторые части
<selectmenu> при помощи специального селектора ::part(name), где name - название части: button, selected-value и listbox. Также доступны псевдоклассы :open и :closed для стилизации открытого и закрытого состояний <selectmenu> соответственно. Полезно для стилизации маркера.selectmenu::part(button) {
/* стили кнопки */
}
selectmenu::part(selected-value) {
/* стили выбранного значения */
}
selectmenu::part(listbox) {
/* стили выпадающего списка */
}
selectmenu:open {
/* стили при открытом выпадающем списке */
}
selectmenu:closed {
/* стили при закрытом выпадающем списке */
}Можно передавать свою разметку, используя слоты. Доступные слоты:
button, selected-value, marker и listbox. Браузер заменит стандартную разметку на ту, что была передана в слот. Атрибут behavior сообщает браузеру поведение, которое нужно добавить элементу. Внутри <option> также можно разместить дополнительную разметку, что позволяет добавить иконки, картинки, многострочный текст и все это стилизовать как нужно.<selectmenu>
<div slot="button">
<svg><!-- ... --></svg>
<button
behavior="button"
></button>
</div>
<option>
<svg><!-- ... --></svg>
<span>Опция 3</span>
</option>
<option>
<svg><!-- ... --></svg>
<span>Опция 4</span>
</option>
</selectmenu>
В слот
listbox можно передать разметку, которая будет использоваться как контейнер для опций. В таком случае нужно указать атрибуты behavior="listbox" и popover="auto" (да, тут используется Popover API). Можно сделать селектор цветов как в MS Word.Когда эту фичу раскатят - не ясно. Поэтому к релизу синтаксис может немного измениться, но слоты и части останутся в таком виде, поскольку это часть стандарта веб-компонентов. Больше примеров и подробное описание можно найти в предложении OpenUI.
UPD: компонент переименовали в
<selectlist>, чтобы не было путаницы с элементом <menu> и паттерном меню.UPD2: компонент слегка переделали, заменив селектор
::part() на псевдоклассы, а также добавив новые вспомогательные элементы <listbox> и <selectedoption>. Работа активно идёт.