<divelopers> – Telegram
<divelopers>
1.03K subscribers
21 photos
253 links
Рандомные мысли про HTML, CSS, доступность, пользовательские интерфейсы, производительность, браузеры и веб-стандарты.

Автор: @alexnozer
Download Telegram
Google I/O 24: The state of CSS and Web UI (часть 2)

Начнём с новых фич, связанных с анимацией. И тут действительно много интересного.

Scroll-driven animations


Представьте сайты, где при прокрутке летают и появляются элементы. Для подобных задач обычно используются библиотеки, вроде GSAP Scrolltrigger. Так вот, Scroll-driven animations — это встроенный способ делать анимации, привязанные к прокрутке или появлению в области просмотра. Причём делать это можно как в CSS, так и в Javanoscript (Web Animations API). Подробнее про Scroll-driven animations, небольшой видео-курс по Scroll-driven animations, примеры на сайте scroll-driven-animations.style, полифилл. Доступно в Chrome и Edge 115+ и Firefox Nightly.

Same-document View Transitions

Одна из горячо обсуждаемых новинок. View Transitions — это API для анимации переходоа между страницами, правда пока только для SPA. При помощи этого API можно реализовать бесшовные переходы между экранами приложения, как на мобильных устройствах. Подробнее про Same-document View Transitions. Доступно в Chrome и Edge 111+.

View Transition Classes

View Transition продолжает развиваться. Новая фича добавляет возможность применять одну анимацию к группе однотипных элементов с указанным классом. Например, можно анимировать изменение порядка карточек в результате сортировки, фильтрации, добавления или удаления их из списка. Подробнее про View Transition Classes. Доступно в Chrome и Edge 125+.

View Transition Types

Другое улучшение для View Transition API — типы, чтобы задавать разные анимации для перехода со одной страницы на другую и обратно. Например, переход с главной на каталог происходит как slide-left (главная уезжает влево, каталог выезжает справа). А обратная анимация slide-right (каталог уезжает вправо, главная выезжает слева). Подробнее про View Transition Types. Доступно в Chrome и Edge 125+.

Cross-document View Transition

А вот это вообще киллер-фича —  анимированные переходы между страницами обычных многостраничных сайтов. И для этого не нужно делать SPA. Кстати, похожее умел делать ещё Internet Explorer 5.5 🌚, а Chrome вот-вот научится. Подробнее про Cross-document View Transition. Доступно в Chrome и Edge 126+.

Scoped transitions, Gesture-driven transitions, Navigation matching in CSS

Всё это про будущие доработки и улучшения View Transition API. Интеракция с частями страницы во время анимации, основанные на жестах анимации (переключение страниц свайпами влево-вправо на телефонах, удаление элементов смахиванием вверх) и полное управление анимацией через CSS.

Animate display and content-visibility on a keyframe timeline

Свойства display и content-visibility не анимируются. Приходится использовать костыли, чтобы красиво показать диалоговое окно. Так вот, появляется возможность анимировать свойство display внутри @keyframes. Свойства применятся в самом начале или конце таймлайна анимации. Подробнее про анимацию display и content-visibility. Доступно в Chrome и Edge 116+ и Safari TP.

transition-behavior: allow-discrete

А если нужно анимировать display при помощи transition? Добавляется новое свойство transition-behavior: allow-discrete, которое включает режим анимации дискретных свойств (в том числе display). Подробнее про transition-behavior. Доступно в Chrome и Edge 117+ и Safari 17.4.

@starting-style

А если хочется анимировать какие-то свойства при появлении элемента? Для этого добавлена директива @starting-style. Она позволяет задавать стартовые значения свойств, которые будут анимированы к новым значениям, указанным для элемента. Подробнее про @starting-styles. Доступно в Chrome и Edge 117+ и Safari 17.5.

overlay

С внедрением <dialog> и Popover API, в браузерах появился отдельный слой top-layer и псевдо-элемент ::backdrop. Есть необходимость как-то это анимировать. overlay даёт возможность делать плавные анимации появления и исчезновения диалогов и попапов в сочетании с @starting-style и allow-discrete. Подробнее про overlay. Доступно в Chrome и Edge 117+.
🔥4
Google I/O 24: The state of CSS and Web UI (часть 3)

Тут рассмотрим новые возможности, связанные с UI-компонентами и примитивами для их создания.

Popover API

Новый API позволяет делать различные выпадающие элементы при помощи кнопки, ряда новых атрибутов и псевдо-классов в CSS. Про это я уже рассказывал ранее и ещё расскажу в ближайшем будущем. Подробнее про Popover API. Доступно в Chrome и Edge 114+, Firefox 125+ и Safari 17+.

Anchor Positioning API

Если вы когда-нибудь делали элементы, которые должны быть привязаны к другим элементам (тултипы, например), то вы использовали что-то вроде Popper или Floating UI. Новый API Anchor Positioning предлагает встроенный в браузеры функционал привязки элементов друг к другу без Javanoscript. В сочетании с Popover API это предоставит возможность реализовывать многие интерфейсные паттерны в простом декларативном стиле без лишних библиотек. Подробнее про Anchor Positioning API и песочница для экспериментов с разными вариантами позиционирования. Доступно в Chrome и Edge 125+.

interesttarget

Доработки Popover API продолжаются. Сейчас для переключения поповера нужна кнопка и клик по ней. Новый атрибут interesttarget даст возможность вместо клика вызывать поповер по ховеру или фокусу на кнопке. Также рассматривается возможность добавить этот атрибут для ссылок. Popover API с interesttarget и Anchor Positioning API позволит создавать тултипы. Подробнее про interesttarget в предложении OpenUI. Фича в разработке, пока не доступна ни в одном из браузеров.

Invokers API


Продолжение идей, заложенных в Popover API. Почему декларативно, при помощи кнопки, можно только скрывать/показывать поповер? Как на счёт других частых действий, для которых пишется Javanoscript? Invokers API добавляет кнопке новые атрибуты, при помощи которых можно декларативно вызывать действия с другими элементами. Например, открыть <dialog> без Javanoscript или поставить <video> на паузу. Подробнее про Invokers API в предложении OpenUI. API доступно в Canary-версиях всех браузеров.

Stylable <select>


Наконец-то появляется решение для давней проблемы — стилизации <select>. Суть в том, чтобы доработать парсер HTML и позволить вкладывать внутрь <select> такие элементы, как <button> и <datalist>, а также вкладывать в <option> любую произвольную разметку. Это даст возможность стилизовать <select>, его шапку, выпадающий список и опции. Подробнее про Stylable Select Element в предложении OpenUI. Доступно в Chrome и Edge Canary.

Exclusive Accordion

Расширение для существующего элемента <details>, которое добавляет ему новый атрибут name. При помощи него можно объединить несколько <details> в группу, где только один элемент может быть раскрыт одновременно. Самый настоящий нативный аккордеон! Подробнее про Exclusive Accordion. Доступно в Chrome и Edge 120+ и Safari 17.2+.

:user-valid и :user-invalid

У полей ввода есть псевдо-классы :valid и :invalid. Проблема в том, что они срабатывают сразу, даже если пользователь ещё не успел провзаимодействовать с полями ввода. Это приводит к плохому пользовательскому опыту. Новые псевдо-классы :user-valid и :user-invalid сработают только если пользователь уже взаимодействовал с полями ввода. Подробнее про эти псевдо-классы. Доступно в Chrome и Edge 119+, Firefox 88+ и Safari 16.5+.

field-sizing: content

Новое свойство CSS для управления размером полей ввода. Представьте задачу: нужно сделать так, чтобы при вводе текста в <textarea>, её размер увеличивался по мере ввода текста. Свойство field-sizing: content как раз решает эту задачу без лишних скриптов. Подробнее про field-sizing. Доступно в Chrome и Edge 123+.

<hr> внутри <select>

Внутрь <select> можно вкладывать только <option> и <optgroup>, другие элементы будут игнорироваться. Если нужно визуально разграничить опции, то применялись различные хаки. Теперь в <select> можно вкладывать элемент <hr>, который будет создавать разделитель между опциями. Мелочь, а приятно. Подробнее про <hr> в <select>. Доступно в Chrome и Edge 119+, Firefox 122+ и Safari 17+.
🔥6👍1
Google I/O 24: The state of CSS and Web UI (часть 4)

Последняя и заключительная часть про новинки HTML и CSS с Google I/O. В этой части посмотрим на различные фичи, улучшающие DX.

CSS Nesting Lookahead

В CSS появилась вложенность, к которой многие привыкли в препроцессорах. В базовой реализации было неудобно добавлять & перед вложенными элементами. Это исправили и теперь писать & не обязательно. Подробнее про Nesting Relaxed Syntax. Доступно в Chrome и Edge 120+, Firefox 117+ и Safari 17.2+.

align-content в блочных элементах

Фича, которая вызвала дикий восторг у аудитории. Мы привыкли к свойству align-content внутри flex и grid. И если нам нужно что-то вертикально выровнять, мы делает контейнер flex или grid только ради того, чтобы применить align-content. Теперь свойство align-content будет работать и внутри block. Подробнее про align-content в блочных элементах. Доступно в Chrome и Edge 123+, Firefox 125+ и Safari 17.4+.

text-wrap: balance и text-wrap: pretty

Новые значения для выравнивания и переноса текста. text-wrap: balance балансирует текст, чтобы длина всех строк в блоке была как можно более равной. Это полезно для заголовков. Подробнее про balance. Доступно в Chrome и Edge 114+, Firefox 121+ и Safari 17.5+. text-wrap: pretty переносит текст таким образом, чтобы в конце текста на новой строке не оказалось одно слово. Подробнее про pretty. Доступно в Chrome и Edge 117+.

word-break: auto-phrase

Ещё одно улучшение для работы с текстом в CSS. Новое значение word-break: auto-phrase позволяет управлять автоматическим переносом и правильно переносить фразы для CJK-языков (Китайский, Японский, Корейский и подобные). Подробнее про auto-phrase. Доступно в Chrome и Edge 119+.

text-spacing-trim

В типографии CJK-языков принято разделять знаки препинания небольшими отступами для лучшей читаемости. Свойство text-spacing-trim как раз включает режим, при котором отступы автоматически добавляются. Фича будет по умолчанию включена в браузерах, которые поддерживают это свойство. Подробнее про text-space-trim и его полное описание в черновике спецификации. Доступно в Chrome и Edge 123+.

Relative Color Syntax

Продолжается работа над цветами в CSS. Relative Color Syntax позволяет изменять компоненты цветов в разных цветовых пространствах и форматах. Например, можно взять цвет в формате oklch и изменить параметры (l - lightness, c - chroma, h - hue), сделать цвет чуть ярче или тусклее, изменить оттенок. Ещё это позволяет конвертировать цвета из одного формата в другой. Подробнее про Relative Color Syntax. Доступно в Chrome и Edge 119+ и Safari 16.4+.

light-dark()

Новая CSS-функция light-dark() принимает два цвета. Первый будет применён для светлой темы (prefers-color-scheme: light), второй — для тёмной темы (prefers-color-scheme: dark). Сейчас это же можно реализовать при помощи Custom Properties и prefers-color-scheme. Но с light-dark() это удобнее. Подробнее про light-dark() и плагин для PostCSS. Доступно в Chrome и Edge 123+, Firefox 120+ и Safari 17.5+.

:has()

:has() — родительский селектор, с помощью которого можно стилизовать элемент в зависимости от его дочерних элементов и их состояний. Вариантов применения уже придумано огромное количество. Интерактивный гайд Ахмада Шадида по :has(). Доступно в Chrome и Edge 105+, Firefox 121+ и Safari 15.4+.

Container Queries

Container queries позволяют менять внешний вид элемента в зависимости от ширины контейнера, а не ширины всего экрана. Можно будет создавать универсальные компоненты, которые будут адаптироваться в зависимости от места использования. Подробнее про Container Queries, Интерактивный гайд Ахмада Шадида по Container Queries. Доступно в Chrome и Edge 106+, Firefox 110+ и Safari 16+.

property

По умолчанию все Custom Properties — строки. Браузер сам преобразует их в нужные типы. Но браузер не понимает, как анимировать из строки в строку. @property решает эту проблему. Директива позволяет указать тип, значение по умолчанию и наследуемость для Custom Properties. Подробнее про @property. Доступно в Chrome и Edge 85+, Firefox 128+ и Safari 16.4+.
🔥5👍3
Результаты State Of HTML 2023 (часть 1)

Опубликованы результаты опроса State Of HTML. С цифрами и выводами можно ознакомиться на сайте опроса. Я сосредоточусь на отдельных моментах.

Опытные разработчики

28% участников — разработчики с опытом 11-20 лет, 24% — с опытом 6-10 лет, 16% — с опытом более 20 лет. Аудитория достаточно опытная.

Нарушения здоровья

20% отметили те или иные нарушения здоровья: когнитивные, проблемы со зрением, проблемы со слухом и нарушения, связанные с мобильностью. Это примерно согласуется со всемирной статистикой. Так что доступность важна.

Список для чтения

В ходе опроса можно было сохранять фичи в список для чтения. Больше всего в список добавляли:
- <datalist>
- <selectlist>
- Popover API
- input.showPicker()
- HTML Media Capture
- inert
- <search>
- Badging API
- Exclusive Accordion
- autocomplete

Сделаю отдельные посты про каждую из этих фичей.

Формы

Главными претензиями к формам, как были, так и остаются — стилизация и проблемы с полями ввода. Также у разработчиков вопросы к механизму валидации, браузерной поддержке, обработке данных форм, доступности, обработке ошибок, contenteditable, управлению состоянием форм и лейблам.

Интерактивность

Разработчики примерно в равной степени используют Javanoscript без фреймворков (89%) и фреймворки (87%) для создания интерактивности. Основные болевые точки: браузерная поддержка, манипуляции DOM, образовательные материалы, зависимость от Javanoscript, обработка событий, веб-компоненты, доступность, управление состоянием, реактивность и стилизация.

Контент

Разработчики активно используют Intl API для форматирования дат, чисел и т.д. Главные боли с контентом: SVG, менеджмент изображений, <iframe>, интернационализация, браузерная поддержка, стилизация, безопасность и приватность, работа с датами, образовательные материалы и проблемы с <input>.
👍3🤓1
Результаты State Of HTML 2023 (часть 2)

Web Components

Тут остановимся подробнее. 42.9% использовали Custom Elements, а 32.5% определяли свои элементы (customElements.define()). То есть часть разработчиков потребляет готовые компоненты, но не создаёт свои. Среди библиотек готовых веб-компонентов отметили Material 3 (Material Web Components). Также в списке есть мой фаворит — Shoelace.

К болям использования веб-компонентов относят: стилизацию, поддержку фреймворков, образовательные материалы, SSR, Shadow DOM, зависимость от Javanoscript, сложность, доступность и несовместимость.

Боли, связанные с разработкой веб-компонентов: образовательные материалы, браузерная поддержка, Shadow DOM, стилизация, сложность, зависимость от Javanoscript, бойлерплейт, SSR, доступность и многословность.

Доступность

Радует, что разработчики в целом используют различные техники доступности. Даже новый элемент <search> уже использовало 11.8%. Ещё более интересно, что предложенный группой OpenUI атрибут focusgroup, который нигде не реализован, использовало 7.4%. Я сам очень жду этот атрибут и подробнее о нём расскажу.

Другие техники доступности, которые применяют разработчики: alt, информативная структура контента, лейблы для полей форм, осмысленный текст в ссылках, контрастные цвета, клавиатурная навигация, видимая рамка фокуса, альтернатива для цветов и курсора мыши, <fieldset> + <legend> и Skip-link. Неплохо.

Боли с разработкой доступных интерфейсов следующие: технические проблемы, образовательные материалы, проблемы на уровне бизнеса, проблемы реализации, проблемы со скринридерами, недостаток инструментов, браузерная поддержка, недоработки WCAG, проблемы с элементами HTML и зависимость от Javanoscript.

Веб-приложения

В этом разделе речь идёт, в основном, о PWA. Я сильно в этом не разбираюсь, поэтому сказать особо нечего.

Боли при разработке веб-приложений (PWA): проблемы на iOS, проблемы с PWA, браузерная поддержка, проблемы с UX, образовательные материалы, Service Workers, проблемы реализации, доступ к нативным API, производительность и уведомления.

Инструменты и другие фичи

Наиболее часто для генерации разметки используются Next.js, Astro и Nuxt. Не смотря на падение популярности, Gatsby всё ещё активно используется. Приятно видеть в списке Eleventy. Всё ещё используют статические генераторы Jekyll и Hugo. Замыкает топ SvelteKit.

Люди используют AI для написания разметки: ChatGPT, Copilot и Bard. Мой опыт использования AI для генерации разметки оказался не очень хорошим.

Некоторые разработчики всё ещё применяют старые элементы: <center>, <marquee>, <font>, <frameset> + <frame>, <blink>, <applet>, <plaintext>, <isindex> и <nextid>.

Выводы

Много болей разработчиков связаны с стилизацией и кастомизацией. Но сдвиги в этом направлении есть, что хорошо. Спасибо проектам Interop и ребятам из OpenUI.

Также достаточно распространённой болью является недостаток образовательных материалов. Разработчики не могут получить информацию, как правильно использовать тот или иной API. Для меня это сигнал, на что стоит обратить внимание при выборе тем для публикации.

Веб-компоненты продолжают развиваться и набирать популярность. Это видно как из цифр опроса, так и по информационному полю.

Растёт и внимание к доступности. Возможно, это связано с ужесточением законов в некоторых странах и грядущим European Accessibility Act. Или же улучшилась ситуация с информацией о том, как лучше разрабатывать интерфейсы. Скорее всего, и то, и другое.
👍5🔥3🤓21
You don't know HTML: <datalist>

Совмещу рубрику You don't know HTML с разбором возможностей, которые чаще всего сохраняли в список для чтения в ходе опроса State Of HTML. Начну с <datalist>.

По спецификации, <datalist> — это набор предопределённых значений для поля ввода. В базовом случае это контейнер для элементов <option>. Он привязывается к <input> при помощи атрибутов list и id. Опции — это готовые варианты, доступные для выбора в качестве значения поля ввода. При этом само поле остаётся редактируемым. Иными словами, это встроенный в браузеры элемент Combobox.

<label for="country"></label>
<input type="text" id="country" list="sugguestions">
<datalist id="sugguestions">
<option value="USA"></option>
<option value="Germany"></option>
<option value="Spain"></option>
<!-- ... -->
</datalist>


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

С точки зрения доступности, <input list> получает встроенную роль combobox и соответствующие ARIA-атрибуты. Предусмотрена клавиатурная навигация: опции можно переключать стрелками и выбирать при помощи Enter или Space, закрыть список можно по Esc, а открыть стрелкой вниз. Однако не все так гладко с доступностью. Заведено issue с описанием проблем.

<datalist> может предоставлять резервный вариант в браузерах, которые про такой элемент не знают. Внутрь <datalist> можно поместить <select> с набором <option>. Если браузер поддерживает <datalist>, то он проигнонирует всё, кроме <option>. Если браузер не поддерживает <datalist>, то он будет считать элемент как <span> и отобразит внутреннее содержимое. На практике такое вряд-ли понадобится, потому что все современные браузеры элемент поддерживают. Но такой способ применения есть.

<label for="country">Country</label>
<input type="text" id="country" list="sugguestions">
<datalist id="sugguestions">
<label for="fallback">(or choose one of them)</label>
<select id="fallback">
<option value="us">USA</option>
<option value="de">Germany</option>
<option value="es">Spain</option>
<!-- ... -->
</select>
</datalist>


<datalist> по-разному взаимодействует с разными типами полей ввода. Он не работает для полей с типами hidden, password, checkbox, radio, file, submit, image, reset и button. Для полей с типами text, search, tel, email, url и number отображается выпадающий список с опциями. Для полей с типами date, month, week, time и datetime-local нужно соблюдать определённый формат значений value у <option>, чтобы подсказки появились. Для range отображаются засечки, к которым привязывается ползунок. Для выбора типа color отображаются цветные квадраты, если value задан в полном или сокращённом формате HEX. На мобильных устройствах своё поведение в зависимости от типа. Примеры можно посмотреть в Доке.

Использовать элемент можно по-разному. Если есть статистика поиска в интернет-магазине, то можно добавить 5 самых популярных товаров в качестве подсказок. Или для поля ввода города добавить наиболее частые варианты. Можно переопределить варианты, которые сгенерировал браузер на основе autocomplete.

Второе дыхание элемент <datalist> получит благодаря предложению от OpenUI. Его суть в том, чтобы переиспользовать <datalist> для стилизации многострадального <select>. Подробнее в следующем посте.

#ydkhtml
4👍4
Элемент <selectlist>

Ранее я уже рассказывал об элементе <selectmenu>. Это предложение от группы OpenUI, которое было призвано решить проблемы стилизации <select>. Новый элемент использует некоторые идеи веб-компонентов и композицию, чтобы можно было собрать и стилизовать выпадающий список с выбором под свои нужды. С 97 версии Chrome и Edge новый элемент можно опробовать за флагом.

Спустя какие-то время, в результате дискуссий в репозитории OpenUI, было принято решение переименовать элемент с <selectmenu> на <selectlist>. По мнению некоторых участников дискуссии, menu в названии может привести к неверному пониманию назначения элемента у разработчиков. Из-за этого элемент могли использовать для создания различных типов меню, а это не то, для чего задуман новый элемент. Меню — это совершенно другой паттерн и семантика.

В какой-то момент с сайта OpenUI пропало предложение что по <selectmenu>, что по <selectlist>. По старым ссылкам располагается страница, которая предлагает перейти на другое предложение — Stylable Select Element. В его URL всё ещё содержится selectlist, а из дискуссий становится ясно, что перед нами дальнейший этап инкубации на тему стилизации <select>.

В новой итерации прнято решение использовать существующие элементы вместо добавления новых. Предлагается использовать комбинацию <select>, <button>, <datalist> и <option> для создания стилизуемых вариантов.

<label for="country">Country</label>
<select id="country">
<button>
<selectedoption></selectedoption>
</button>
<datalist>
<option value="us">
<img src="usa.jpg" alt="flag of USA">
USA
</option>
<option value="de">
<img src="germany.jpg" alt="flag of Germany">
Germany
</option>
<option value="es">
<img src="spain.jpg" alt="flag of Spain">
Spain
</option>
</datalist>
</select>


Наличие внутри <select> элемента <button> и/или <datalist> является сигналом для парсера, что это стилизуемый вариант и с ним нужно работать иначе. Это подразумевает доработку парсера, потому что сейчас всё, кроме <option>, <optgroup> и <hr> игнорируется.

В CSS предлагают добавлять appearance: base-select, чтобы сообщать браузеру, что это не обычный селект, а стилизуемая версия. Дополнительно предлагается добавить псевдо-классы :open и :closed, тип кнопки type="popover", элемент <selectedoption> для отображения выбранного варианта и много чего ещё. Более подробно об этом можно узнать в самом предложении Stylable Select Element.
5👍4
Условия в CSS

Исторические вещи происходят. Лия Веру поделилась, что было принято решение по условному оператору в CSS. Новая функция if() будет добавлена в спецификацию CSS Values and Units Module Level 5. Когда она появится в браузерах, это вопрос. Но она там появится рано или поздно. Можно будет делать такое:

.element {
background: if(
style(--variant: success), var(--green)
);
padding: if(
var(--2xl), 1em,
var(--xl) or var(--m), .5em
);
}
🔥12🤔2
Линии во flexbox и grid

Небольшое предисловие. В CSS есть Multi-Columns Layout. Это возможность разбить текст внутри элемента на несколько колонок (фрагментов по умному) и управлять их поведением. Многие об этом не знают, потому что подобные задачи встречаются не часто. В основном это нужно в сфере типографии. Но иногда и при вёрстке сайтов можно применить.

У мульти-колонок есть свойство column-gap для управления отступами между колонками. Впервые свойство появилось именно в мульти-колонках и потом уже было использовано во флексах и гридах в паре с row-gap и сокращённым свойством gap.

Ещё у мульти-колонок есть возможность отображения линий между колонками. Делается это при помощи свойства column-rule. Его синтаксис такой же, как у border: толщина, тип и цвет. Рисуется вертикальная линия между колонками, на тех местах, где находятся отступы.

А почему бы не сделать такую возможность во флексах и гридах? Я, например, сталкивался с ситуациями, когда это было нужно. Приходилось что-то придумывать. Об этом подумали в команде Edge и выкатили эксплейнер с предложениями по линиям между флекс-элементами и ячейками грида.

В предложении не просто описана возможность добавления линий, а предусмотрены различные сценарии применения. Вертикальные и горизонтальные линии, разные стили, чередование, пересечение, смещение, перекрытие и ещё много чего. Всё рассказать сложно, проще посмотреть на иллюстрации и примеры кода.
👍4🔥4
Popover API

Popover API недавно стал поддерживаться всеми современными браузерами, а также попал в топ списка для чтения по результатам State of HTML 2023. Это значит, что пришло время поближе познакомиться с этим API.

Popover API — это механизм для создания различных всплывающих элементов интерфейса (поповеров). Механизм преимущественно декларативный, JavaScript не требуется. При этом механизм добавляет много полезного: открытие/закрытие по кнопке, закрытие по Esc и клику вне поповера, встроенные aria-атрибуты, возврат фокуса.

Поповеры бывают двух видов (на данный момент): автоматические и ручные. Автоматический поповер создаётся при помощи кнопки с атрибутом popovertarget, который содержит id поповера. У самого всплывающего элемента при этом должны быть указаны атрибуты popover или popover="auto" и id.

<button
type="button"
popovertarget="more"
>
More info
</button>

<div id="more" popover>
<p>More information...</p>
</div>


При нажатии на кнопку, отображается связанный поповер. При повторном нажатии на кнопку, нажатии клавиши Esc или нажатии в любом месте вне поповера, он скрывается.

Ручной поповер создаётся при помощи атрибута popover="manual". Такой поповер не будет закрыт при нажатии в произвольном месте. Для закрытия требуется кнопка с атрибутом popovertargetaction="hide". Также закрыть ручной поповер можно при помощи Esc.

<button
  type="button"
  popovertarget="more"
>
  More info
</button>

<div id="more" popover="manual">
  <p>More information...</p>
<button
type="button"
popovertarget="more"
popovertargetaction="hide"
>
Close
</button>
</div>


Помимо значения hide (только закрыть) доступны значения show (только показать) и toggle (переключить видимость).

Сам поповер вырывается из основного потока и помещается в специальный слой top-layer, который всегда будет выше любого z-index. У поповера есть псевдо-элемент ::backdrop, что позволяет стилизовать задний фон (оверлей). Открытый поповер можно стилизовать через псевдо-класс :popover-open. По умолчанию поповер располагается по центру экрана, а его размеры определяются по контенту. Подробнее про стандартные стили поповера можно прочитать в блоге Mayank.

Кнопка управления поповером получает встроенные атрибуты aria-expanded, и aria-details. Если у поповера роль generic, то она заменяется на group, иначе используется встроенная роль или указанная в атрибуте role. Поповер становится следующим элементом в последовательности табуляции, даже если между ним и кнопкой есть другие интерактивные элементы. При закрытии поповера через Esc, фокус возвращается на кнопку, с помощью которой он был показан. Подробнее про доступность поповера в блоге Hidde.

В Javanoscript у кнопки управления поповером доступны методы showPopover(), hidePopover() и togglePopover() для программного отображения, скрытия и переключения поповера.

API доступно в Chrome и Edge 114+, Firefox 125+ и Safari 17+. Для более ранних версий можно использовать полифил. Это позволит избавиться от JavaScript-библиотек, которые воспроизводят функциональность Popover API. Когда поддержка будет лучше, полифил можно будет отключить.

API продолжает развиваться. В будущем нас ожидают доработки: popover="hint", ::tooltip и role="tooltip" для тултипов, Anchor Positioning API для позиционирования и т.д.

Забавный факт: известно, что все эти новые атрибуты из Popover API объявят устаревшими. Дело в том, что новый Invoker Commands API принесёт с собой новые атрибуты, которые заменят текущую реализацию Popover API. Но об этом в другой раз.
10🤗1
Как не мучать пользователя плохими контролами

Буду иногда делиться записями докладов, которые я смотрю и которые кажутся мне интересными, важными и близкими.

Буквально вчера опубликовали запись доклада Ильи Бирмана про плохие контролы. Илья на примере разных сайтов показывает, с какими проблемами сталкиваются пользователи, когда дизайнеры и разработчики плохо продумали UX.

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

Рекомендую посмотреть доклад.
👍6🔥6
Результаты State of JS

Опубликованы результаты опроса State of JS 2023. Опрос посвящён JavaScript и его экосистеме: фреймворкам, библиотекам тестирования, сборщикам, утилитам и т.д. С результатами можно ознакомиться по ссылке.
👍2🌚1
Случайная задачка: группа только с кнопками

Совершенно случайно мне в голову пришла одна задачка. Звучит она так:

Можно ли в CSS выбрать элемент, внутри которого находятся только кнопки, и этих кнопок две и более?


Да, иногда приходят такие мысли 😅.

Где это может пригодиться? Ну, предположим, разрабатывается компонент табов, где должен быть элемент с ролью tablist, внутри которого могут быть только элементы с ролью tab и как минимум два таких.

Вернёмся к изначальной задаче с кнопками.
Ответ: так сделать можно. И вот как:

[role="group"]:has(> button:nth-child(2)):not(:has(> :not(button))) {
width: fit-content;
border: 2px solid green;
}


И разметка:

<div role="group">
<button type="button">Action 1</button>
<button type="button">Action 2</button>
<button type="button">Action 3</button>
</div>


Абсолютно нечитаемое месиво из селекторов, но оно работает. Вся магия кроется в сочетании :has(), :not() и :nth-child(). Что там вообще происходит? Мы говорим:
1) выбери элемент с атрибутом role="group"
2) внутри которого вторым дочерним элементом является кнопка
3) и внутри которого нет дочерних элементов, которые не являются кнопкой

Иными словами: выбери группу, в которой есть как минимум две кнопки и нет ничего кроме кнопок.

Перекладывая эту идею на табы, можно получить такой селектор:

[role="tablist"]:has(> [role="tab"]:nth-child(2)):not(:has(> :not([role="tab"]))) {
  /* стили */
}
🤯5👍1
Дополнение к предыдущему посту

Зачем вообще писать такие монструозные селекторы? Их невозможно читать, они обладают высокой специфичностью и противоречат общепринятым подходам к неймингу. Какая в этом может быть практическая польза?

Поиск подходящих элементов

Допустим, разрабатывается скрипт. Этот скрипт должен добавлять поведение в разметку. Для правильной работы скрипта нужна определённая структура, классы и атрибуты. Можно, найти корневой элемент, проверить его атрибуты, затем получить дочерние элементы и проверить их. Для этого придётся писать много JavaScript с if-ами и перемещаться по DOM. Вместо этого, при помощи метода querySelector() и сложного селектора, можно сразу получить нужный элемент, который удовлетворяет всем условиям.

Проверка элементов

Бывают задачи, когда разметка вставляется извне и её нужно проверить и что-то сделать на основе этого. Например, вставка разметки из WYSIWYG-редактора, передача элементов в Shadow DOM через слоты, композиция элементов и т.д. Как и в предыдущем примере, можно проходиться по дереву и производить проверки. В качестве альтернативы, можно использовать метод matches() со сложным селектором и проверять элементы на соответствие.

Classless библиотеки

Экзотичный, но всё же существующий подход. Его суть в том, чтобы написать таблицу стилей, которая не содержит селекторов по классу, полагается на семантические элементы, атрибуты, сочетания элементов и вложенность. Вполне себе решение для оформления демок, простых страниц, возможно даже документации. Примеры таких таблиц стилей:
- Water.css
- Simple.css
- matcha.css
- pico.css
- new.css
- и другие

Отладка вёрстки

Если взять хорошие практики HTML, найти несоответствующую им разметку с помощью сложных селекторов и подсвечивать броским цветом такую разметку, то получится интересный инструмент для отладки вёрстки в браузере. Хейдон Пикеринг ещё в 2013 году сделал подобную библиотеку REVENGE.CSS, в 2016 году выступил с докладом об этом, а в 2024 году переосмыслил идеи под новые возможности CSS и написал статью об этом у себя в блоге.

Тестирование вёрстки

Идею из предыдущего абзаца можно завернуть в JavaScript, который затем запускать в браузере, IDE, на CI/CD или в Storybook. Получится своеобразный линтер и набор тестов для разметки. Можно дописать специфические для компонентов сложные селекторы и отслеживать, что все атрибуты и дочерние элементы на месте, они правильно вложены и нет ничего лишнего. Если что-то изменится, то компонент перестанет соответствовать селектору, значит тест не пройден.

Потому что CSS так может

Действительно, а почему бы и нет? Это современный CSS, который работает во всех актуальных версиях браузеров. Полезно потренироваться и знать, что CSS так в принципе может. Вполне возможно, что в какой-то ситуации эти знания пригодятся и помогут решить задачу на реальном проекте, сделать демку на Codepen, уменьшить количество проверок и условий в JavaScript. Это как регулярные выражения, но в CSS. А регулярные выражения полезны и, порой, незаменимы, хотя выглядят как месиво из случайных символов.
👍4🤓1
Подключение шрифтов

Иногда в исходниках проектов, даже свежих, можно обнаружить примерно такой код:

@font-face {
font-family: 'Roboto Regular';
font-style: normal;
font-weight: 400;
src: local('Roboto'),
url('roboto-regular.eot?#iefix') format('embedded-opentype'),
url('roboto-regular.woff2') format('woff2'),
url('roboto-regular.woff') format('woff'),
url('roboto-regular.ttf') format('truetype'),
url('roboto-regular.noscript#Roboto') format('noscript');
}


Такой сниппет может повторяться для каждого семейства шрифта, толщины и стиля. Сопровождается это папкой fonts с десятом шрифтов разных форматов. Ноги растут из онлайн-генераторов, например, шрифтобелки. На вход поступают шрифты в формате ttf. Далее происходят тонкие настройки, смысл которых понимают только специалисты по шрифтам. На выходе получается архив с готовым CSS и той самой папкой fonts. Это удобно, потому что руками так делать не хочется.

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

1) не используйте local(). Эта функция пытается найти зарегистрированный в операционной системе шрифт и использовать его. На первый взгляд хорошая идея: экономим трафик, не ходим в сеть, переиспользуем ресурсы, быстрее отображаем текст. На практике же с local() много проблем. Шрифт может быть зарегистрирован под другим названием, на устройстве может быть другая версия шрифта, также локальные шрифты используются для фингерпринтинга.

2) достаточно формата woff2. Времена, когда нужны шрифты разных форматов, уже прошли. Все браузеры умеют работать с woff2. На данный момент это самый эффективный формат шрифта для веба, который должен использоваться по умолчанию. Если нужно поддерживать IE, то к woff2 можно добавить woff. Но не нужно генерировать, хранить и подключать noscript, eot, ttf и другие менее эффективные и старые форматы.

3) указывайте одинаковое имя семейства в font-family и разные значения font-weight и font-style. Не нужно называть шрифт одного семейства разными именами, например 'Roboto Regular' и 'Roboto Bold'. Назовите оба 'Roboto', а в font-weight и font-style отразите различия. Браузер сам определит, какой шрифт применить, без необходимости каждый раз указывать font-family.

4) указывайте способ отображения шрифта. В @font-face укажите свойство font-display со значением swap, optional или fallback, в зависимости от целей. Это важно для увеличения скорости загрузки, предотвращения сдвигов макета и общего восприятия загрузки сайта.

5) не подключайте шрифты с Google Fonts через <link>. Сгенерируйте шрифт в Google Fonts, скачайте их локально и взьмите сгенерированные сниппеты CSS.

6) создавайте подмножества (subsetting) шрифтов в сочетании со свойством unicode-range. Если язык сайта русский, то нет смысла держать в шрифте многие латинские, японские, китайские и прочие глифы. Для этого шрифт можно разбить на несколько более мелких. В одном оставить кириллицу, цифры и знаки препинания, в другой вынести латиницу и всё остальное. Затем указать это в свойстве unicode-range и браузер скачает только тот шрифт, символы из которого есть на странице. Сам файл при этом будет весить меньше.

7) подключайте основной шрифт в HTML при помощи <style>. Так браузер обнаружит шрифт сразу при получении HTML страницы и не будет ждать загрузки и обработки CSS. Шрифт загрузится и применится раньше. Это позволит избежать вспышек нестилизованного текста (FOUT).

8) предварительно загрузите основной шрифт при помощи <link rel="preload" as="font" format="font/woff2" crossorigin>. Браузер начнёт загрузку шрифта заранее, ещё до того, как фактически обнаружит ссылку. В итоге шрифт частично или полностью будет загружен к моменту его обнаружения. Это также позволяет бороться с FOUT.

9) используйте вариативные шрифты. Файл с вариативным шрифтом хоть и весит больше, но если вариаций шрифта слишком много, то вариативный шрифт обеспечит выигрыш по размеру.

Также ссылки для чтения:
- Best practices for fonts
- Optimize web fonts
- Статьи Зака Лезермана про шрифты
🔥6👍2👀2
You don't know HTML: input.showPicker()

Фича из опроса State Of HTML 2023 — input.showPicker(). Это выглядит как JavaScript-метод (так оно и есть), может возникнуть вопрос: причём тут HTML? На самом деле этот метод описан именно в стандарте HTML. Это маленькое, но полезное улучшение для элементов форм.

Метод showPicker() предназначен для программного вызова системных пикеров. Метод доступен у элемента <input> с типами date, month, week, time, datetime-local, color, file, у полей с атрибутом autocomplete, у полей с атрибутом list в сочетании с элементом <datalist> и у <select>. При вызове метода отображается стандартный системный попап для выбора значения, как если бы пользователь нажал на поле самостоятельно.

<input type="file">
<button type="button">Upload File</button>
<noscript>
const button = document.querySelector('button');
const input = document.querySelector('input');

button.addEventListener('click', () => {
try {
input.showPicker();
} catch (error) {
// Обработка ошибок
}
});
</noscript>


В примере кода видно, что с помощью try-catch перехватываются исключения. Метод выбросит исключение NotAllowedError, если пользователь как-либо не взаимодействовал со страницей: скролил, кликал. Это сделано из соображений приватности. Если поле нельзя изменять, например оно в состоянии disabled или readonly, будет выброшено исключение InvalidStateError. Если элемент <select> не отображается на экране, будет выброшено исключение NotSupportedError. И если домен не same origin, то выбрасывается исключение SecurityError.

Этот метод позволяет прятать стандартные поля ввода, но вызывать их функции в виде системных пикеров. Особенно это актуально для для разработки кастомных полей для загрузки файлов на основе <input type="file">.

#ydkhtml
👍7🔥4
5 правил ARIA

Accessible Rich Internet Application, или же сокращённо ARIA — это расширение HTML, предоставляющее набор атрибутов для расширения семантики HTML и разработки доступных сайтов и приложений.

Существует документ под названием Using ARIA, в котором даны рекомендации и описаны 5 правил использования ARIA.

Первое правило

Используйте встроенные в HTML элементы и атрибуты для передачи нужной семантики вместо использования ARIA. Иными словами: первое правило ARIA — не используйте ARIA.

Второе правило

Не меняйте семантику встроенных элементов без острой необходимости.

Вместо этого:

<h2 role="tab">heading tab</h2>


Лучше сделать так:

<div role="tab">
<h2>heading tab</h2>
</div>


Третье правило

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

Скрипт должен реагировать на нажатие отдельных клавиш или их сочетаний при взаимодействии с компонентом.

Четвёртое правило

Не используйте role="presentation" (синоним role="none") и aria-hidden="true" на интерактивных элементах.

Не делайте так:

<button role="presentation">
press me
</button>


Или так:

<button aria-hidden="true">
press me
</button>


Или так:

<div aria-hidden="true">
<button>press me</button>
</div>


Пятое правило

У всех интерактивных элементов должно быть имя. Это имя должно быть указано одним из доступных способов (<label>, aria-label, aria-labelledby и т.д.)
👍6🔥42💯2
Что на счёт элемента <denoscription>?

Таким вопросом задалась Сара Суиден в твиттере. В HTML есть элемент <label for>, с помощью которого можно задать имя встроенным элементам <input>, <textarea>, <select>, <button>, <meter>, <progress>, <output> и FACE (Form-associated Custom Elements). Если у элементов не заданы атрибуты aria-label и aria-labelledby, то текст из <label> используется как имя.

Почему бы не добавить аналогичную возможность для указания aria-denoscription/aria-describedby? На данный момент нет способа сделать это без ARIA. С новым элементом это может выглядеть так:

<label for="password">Пароль</label>
<input type="password" name="password" id="password">
<denoscription for="password">Пароль должен содержать не менее 8 символов, а также включать как минимум одну цифру, одну букву и один символ пунктуации.</denoscription>


Элемент создаёт привязку с описанием, которое будет озвучиваться программами чтения с экрана, если эта функция включена. Это позволит следовать правилу "не использовать ARIA".
👍6🤔1
Classless CSS

CSS-библиотеки почти всегда полагаются на классы. Сразу на ум приходит классический представитель такого подхода — Bootstrap. Есть и другие: Bulma, UIKit, Foundation и т.д.

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

На моё удивление, таких библиотек достаточно много. Есть простые реализации, напоминающие улучшенный normalize.css. Они стилизуют базовые элементы HTML, чтобы голая страница выглядела более-менее симпатично, лучше, чем со стандартными стилями браузера.

Есть и продвинутые реализации. Они предлагают базовую раскладку страницы и некоторые компоненты. Например, <nav> с нумерованным списком <ol> с ссылками <a> внутри <li> будет выглядеть как хлебные крошки. В таких библиотеках используются более сложные селекторы с комбинаторами и иногда :has(), но всё ещё без классов.

Вот два источника с примерами classless библиотек: github-репозиторий и сайт cssbed. Думаю, в интернете можно найти еще что-то подобное.

Вопрос, который может возникнуть: зачем такие библиотеки нужны? Вот несколько примеров использования:
- прототипирование
- создание тестовых, отладочных и служебных страниц
- более красивые демки для образовательных целей
- быстрое создание простого сайта-визитки, портфолио, блога, документации
- создание стилизованных страниц, сгенерированных из Markdown
- альтернатива normalize/reset
- основа для создания своей библиотеки или темы

В общем, применимая штука. Тем более, что для работы достаточно просто вставить <link> в <head> и всё будет работать. У меня даже возникла идея сделать свою реализацию classless-библиотеки 🤔
🔥8👍2
Как я перестал верить технологиям

Рекомендую к просмотру доклад Алексея Симоненко "Как я перестал верить технологиям". Это один из моих любимых докладов. Не смотря на то, что он 2016 года, он всё ещё актуален. Примеры кода из 2016 года могут выглядеть странно, но в этом докладе важен не код, а суть.

Основные тезисы доклада:
- Мы любим решать сложные задачи и не любим доводить дело до конца
- Выбор модных технологий не даёт никаких преимуществ новому продукту
- Самое важное — это продукт, а не технологии
- Делайте продукты для людей, вместо возьни с технологиями

Приятного просмотра!
👍6🔥4
Баги в Chrome

Обычно Chrome выступает в роли эталонного браузера, в котором всё работает. Поэтому сейчас модно жаловаться на Safari и иногда Firefox за баги и отсутствие поддержки некоторых фич.

Но за последние две недели я дважды столкнулся с багами в Chrome, тогда как в других браузерах (Firefox и Safari) все работало как нужно. Ничто не идеально. В таком сложном ПО, как браузеры, есть огромное количество багов. Во всех из них. И браузеры работают сообща над их исправлением в рамках инициативы Interop.

Отдельно хочу сказать про "Safari — новый IE". Кажется, некоторые современные разработчики забывают о таком понятии, как кроссбраузерность. Это всё ещё актуально. Задача разработчика, который делает веб-интерфейс, позаботиться о том, чтобы он выглядел и работал одинаково во всех целевых браузерах.

Кроссбраузерность — это навык, которым должен обладать профессиональный разработчик. Тем более, что сейчас ситуация обстоит намного лучше: есть Can I Use, Baseline, Web Platform Status, уже упомянутый Interop, Browserslist, Autoprefixer и прочие инструменты.
🔥53🤝3