Сегодня я хочу рассмотреть предложенную функцию HTML, которая может в итоге заменить множество пользовательских компонентов ввода на основе <div>: <selectmenu>.

CSS это круто

Позвольте мне начать с CSS. CSS — это фантастика, потому что уже более 25 лет он позволяет нам решать, как должны выглядеть наши веб-сайты. Но так было не всегда. До появления CSS вы могли определять только структуру своих страниц, а браузеры определяли их внешний вид.

Перенесемся в настоящее, CSS не просто существует, он стал чрезвычайно универсальным. У нас есть grid’ы, CSS-переменные, преобразования через transform и многое другое, и все это довольно хорошо работает в разных браузерах. Основной принцип CSS остается неизменным: стили — это подсказки. То, как выглядят веб-сайты, зависит от предпочтений пользователей, браузеров и веб-разработчиков.

Но, возможно, в вашей дизайн-системе ваш select имеет очень специфические стили. Тени вокруг списка, особые настройки отступов… или ваш select содержит больше, чем просто строки текста, например флаги с названиями стран или аватары с именами пользователей. Элемент <select> не позволит вам сделать всё это на CSS. Здесь на сцене появляется <selectmenu>.

Части selectmenu

Элемент <selectmenu> — это новый элемент HTML, предложенный Open UI Community Group. Он еще не попал в спецификацию HTML, но его прототип находится в Chromium. Вы можете проверить это, включив флаг «Experimental Web Platform Features» (перейдите на страницу about:flags и найдите этот флаг).

Когда вы используете <selectmenu>, вы обнаружите, что оно состоит из разных частей:

<select> - корневой элемент

<button> — кнопка, нажав на которую, вы откроете select

<selected-value> - текущее выбранное значение

<marker> - стрелка, которая находится в кнопке

<listbox> - всплывающее окно, которое открывается при нажатии на кнопку

<option> — параметры в списке (как и в обычном <select>)

<optgroup> — необязательный способ группировки опций (как и в обычном <select>)

Источник: Anatomy of the selectmenu

Стилизация selectmenu

Стилизация частей

В CSS Shadow Parts 1, который в настоящее время находится в стадии рабочего черновика (Working Draft) (т. е. еще не является полноценным стандартом), вводится новый псевдоэлемент, позволяющий стилизовать части теневых корней: ::part().

Подождите, разве Shadow DOM не был чем-то специфичным для веб-компонентов? Да. Но то, как <selectmenu> реализован в браузере, похоже на веб-компонент. Вы можете смотреть на него как на веб-компонент, который поставляется с браузером.

С помощью ::part вы можете стилизовать различные части так, как они описаны выше, например, чтобы стилизовать список, вы должны написать:

selectmenu::part(listbox) {
  box-shadow: 3px 3px 3px 3px hotpink;
}

Или, может быть, вы хотите изменить внешний вид стрелки:

selectmenu::part(marker) {
  box-shadow: 3px 3px 3px 3px hotpink;
}

(<marker> еще не добавлен в объяснение selectmenu, но это было утверждено на собрании Open UI)

Состояние стилей

Вы также сможете стилизовать selectmenu в зависимости от того, открыто оно или закрыто, используя псевдокласс :open:

selectmenu {
  border: 2px solid black;
}

selectmenu:open {
  border-color: hotpink;
}

Или, может быть, вам нужен другой маркер, когда selectmenu открыто:

selectmenu::part(marker) {
// regular
}

selectmenu::part(marker):open {
// open
}
Разные иконки в открытом и закрытом состояниях
Разные иконки в открытом и закрытом состояниях

Также будет псевдокласс :closed для стилизации закрытого состояния. Это было бы эквивалентно :not(:open). Псевдоклассы:open и :closed определены в Element Display State section of Selectors, Level 4.

Кастомизация, выходящая за рамки простых стилей

Вы также можете заменить части, показанные выше, на свою собственную разметку. Части, показанные выше, представлены как «слоты», что означает, что вы можете добавить свою собственную древовидную структуру в разметку и использовать её для замены какой-либо части.

Например, вот как вы замените иконку чем-то другим:

<selectmenu>
  <div slot="marker">
    <!-- your own selectmenu open icon goes here -->
  </div>
</selectmenu>

Все, что находится внутри этого div будет использовано вместо стандартной иконки на кнопке, чтобы открыть selectmenu.

В принципе, <selectmenu> позволит вам делать подобные вещи с каждой из частей, чтобы вы могли заменить кнопку или опции. Это дает разработчикам большую власть, а вместе с ней и ответственность. Итак, предостережение: вложение неправильных элементов в части selectmenu, может быстро привести к «HTMHell». Например, что, если вы поместите в опцию больше, чем просто текст — скажем, аватары — но браузеры и вспомогательные технологии ожидают только текст? Или что, если вы поместите кнопку в опцию? Подобные вложенные интерактивные элементы рискуют нарушить работу конечных пользователей в случаях, когда браузер или вспомогательные технологии не смогут волшебным образом исправить это, поэтому будьте осторожны.

Текущий статус

В настоящее время selectmenu находится в стадии «инкубации» в Open UI Community Group и разрабатывается в Chromium за флагом.

А что насчет других браузеров и браузерных движков? Я не уверен, что произойдет в Safari или Webkit, но люди из Firefox (Mozilla) присоединяются к призывам Open UI. Цитата из «The Declarative Web» посвящённая видению компании Mozilla открытости веба:

[в Интернете встроенные элементы управления] часто недостаточно оформлены и имеют несовместимую внутреннюю структуру в разных браузерах, что затрудняет их визуальное согласование с остальной частью веб-страницы. Мы хотим заполнить эти пробелы и рады видеть, что, благодаря стараниям OpenUI, уже есть успехи в этой области.

Чтобы <selectmenu> стало реальностью, ему нужно будет перейти к стандартам, а затем получить реализацию в браузерах. Пока сложно сказать, когда это произойдет.

Резюме

Итак, вкратце: <selectmenu> — это новое предложение, которое добавит новый элемент управления на веб-платформу, который по умолчанию похож на <select>, но может быть оформлен и настроен практически любым способом, который вы хотите. Меня особенно радует возможность использовать ::part() для стилизации частей, и слегка беспокоит возможность полной замены частей, поскольку это может нарушить доступность, если заменить её неправильными вещами.

Вы можете поиграть с <selectmenu> сегодня в Microsoft Edge Canary или Google Chrome Canary и сообщить о проблемах в репозитории Open UI.

Комментарии (13)


  1. nin-jin
    24.12.2022 22:17
    +8

    Прекрасно. Ждём стилизацию датепикера ещё через 10 лет.


    1. funca
      25.12.2022 00:28
      +4

      Веб всю историю пытается усидеть на трёх стульях. С одной стороны это желание дать пользователям привычный UX (что в переделе возможно лишь при использовании нативных контролов операционной системы). С другой - стилизация всего ради удовлетворения эстетических прихотей разработчиков либо их менеджеров (а значит отказ от нативных контролов в пользу самописных аналогов). И третья - не дать браузеру превратиться в полноценный кроссплатформенный UI toolkit (по типу XUL, XAML и т.п).


      1. sshikov
        25.12.2022 09:43
        +3

        Вы так говорите, как будто это что-то плохое.

        Стилизация всего — дело вполне осмысленное. Иначе вы навсегда будете привязаны к тем возможностям, что имеют нативные контролы. И всегда будете ими ограничены.

        То есть да, пытается. Я не вижу в этом ничего плохого. Потребности разные. Кому-то нужно первое, кому-то второе. А третье — это попытка ограничить сложность. В том числе — хорошо бы научиться наконец переиспользовать все что можно от нативных контролов, чтобы не переписывать все с нуля, а писать только и именно то, что нужно.


        1. nin-jin
          25.12.2022 10:14

          Нативные контролы не имеют смысла в кастомном дизайне. Тут надо либо контролы в дизайне сайта иметь (а натив не настолько кастомизируем), либо дизайн сайта мимикрировать под систему (а тут любой кастомный элемент страницы превращается в 100500 версий под разные системные дизайны).


          1. sshikov
            25.12.2022 10:36

            >Нативные контролы не имеют смысла в кастомном дизайне.
            Так я и говорю, что не всем нужен кастомный дизайн. Иногда наоборот хочется походить на нативное приложение (и менять дизайн при изменении настроек системы). Осмысленно ли это само по себе? Наверное не всегда, но в жизни такое встречается.


        1. funca
          25.12.2022 18:48
          +2

          Вы так говорите, как будто это что-то плохое.

          Скорее это что-то сложное. Написать кастомный контрол, имитирующий поведение нативных это дорого. Я имею ввиду полноценную поддержку нюансов различных устройств ввода и вывода, внутренней навигации, масштабирования и т.п. В нашем энтерпрайзе резко отказались от большинства кастомных контролов в вебе как только появились риски комплайнса по части a11y. Внезапно визуальная разница и хотелки перестали быть такой уж важной проблемой.


          1. sshikov
            25.12.2022 19:05
            +1

            А. Ну тогда я не совсем понял посыл исходного коммента.

            Сложно конечно. Вот как это ни удивительно, но в моей практике писать свои контролы проще всего было для Flex (который надстройка над Flash). И вот это вот все давненько уже было — а по сути с тех пор лучше особо не стало. Дорого и сложно. И баги, зачастую самые тупые. Скажем, некий явно кастомный контрол, вроде того, что тут описан в тексте. В поле ввода не работает удаление по кнопке backspace.

            > риски комплайнса по части a11y
            Слишком дорого поддерживать одновременно и хотелки, и a11y?


            1. funca
              25.12.2022 19:57
              +2

              Когда вы используете стандартные контролы, то проблемы с a11y в этой части перееадресуются разработчикам браузера. Если кастомные - то это ваша ответственность (даже если вы купили библиотеку у вендора или взяли из open source). Конечно, можно делать две версии: одну соответствующую законным требованиям, а вторую - эстетическим. Но тут в дело вступают деньги.

              Проблема с a11y в том, что поддержка добавляет изрядную пачку нефункциональных требований, а бардак по части браузеров и сопутствующих решений здесь как в нулевые.


              1. sshikov
                25.12.2022 20:05

                Ну да, я примерно это и предполагал.


  1. maXimus2031
    25.12.2022 10:25
    +8

    добавить туда еще input:text для поиска и цены ему не будет. А то в интернете столько разных реализаций, что постоянно приходится делать свой вариант)


  1. jershell
    25.12.2022 17:55

    Наверное стоит уходить от тегов в развитие канвас элементов посредством wasm, а не вот это вот всё. На текущий день у альтернативного подхода есть проблемы, отсутствие людей с ограниченными возможностями и вялое развитие wasm.


    1. jershell
      25.12.2022 19:45

      *поддержки для


    1. alexander222
      26.12.2022 00:16

      Вам стоит посмотреть в сторону flutter, для веба он примерно так и рендерит.