Разница между aria-selected, aria-checked, aria-current и aria-pressed
В стандарте ARIA есть состояния, которые можно применять к элементам. Среди них есть несколько довольно похожих на первый взгляд:
-
-
-
-
-
-
-
Применяется у следующих элементов:
-
-
-
-
-
-
-
-
-
Применяется к следующим элементам:
-
-
-
-
-
-
-
У
-
-
-
-
-
-
-
Назначение
-
-
-
-
Таким образом все четыре атрибута хоть и обозначают некоторое текущее состояние элемента, но отличаются по смыслу и применимости. Краткая сводка:
-
-
-
-
#a11y
В стандарте ARIA есть состояния, которые можно применять к элементам. Среди них есть несколько довольно похожих на первый взгляд:
-
aria-selected;-
aria-checked;-
aria-current;-
aria-pressed.aria-selected обозначает состояние выбора элемента внутри виджетов с одиночным или множественным выбором. Принимает значения:-
true — элемент выбран;-
false — элемент не выбран;-
undefined — элемент не выбираемый.Применяется у следующих элементов:
-
option в listbox;-
treeitem в tree;-
gridcell или row в grid;-
gridcell или row в treegrid;-
tab в tablist.aria-checked обозначает состояние отметки флажка, радио-кнопки, переключателя, отмечаемых пунктов меню или группы, состоящей из отмечаемых элементов со смешанным состоянием. Принимает значения:-
true — элемент отмечен;-
false — элемент не отмечен;-
mixed — элемент в смешанном (indeterminate) состоянии и связан с группой других отмечаемых элементов;-
undefined — элемент не отмечаемый.Применяется к следующим элементам:
-
checkbox;-
radio (кроме mixed);-
switch (кроме mixed);-
option в listbox;-
menuitemcheckbox в menu или menubar;-
menuitemradio в menu или menubar (кроме mixed);-
treeitem в tree.У
option и treeitem можно использовать aria-selected и aria-checked. Подойдёт любой из них. Но рекомендуется для одиночного выбора использовать aria-selected, а в случае множественного выбора использовать aria-checked.aria-current обозначает текущий элемент в контейнере или наборе связанных элементов. Может быть установлен на любой элемент, но принимает в качестве значения один из предустановленных токенов:-
page — элемент визуально выделен как текущая страница из набора страниц, подходит для активной ссылки в меню или хлебных крошках;-
step — элемент визуально выделен как текущий шаг в многошаговом процессе, подходит для визардов и многошаговых форм;-
location — элемент визуально выделен как текущее положение на странице, экране или процессе;-
date — элемент визуально выделен как текущая дата в виджете календаря или другом наборе дат;-
time — элемент визуально выделен как текущее время в таблице времени или другом наборе времени;-
true — элемент визуально выделен как текущий в наборе связанных элементов без дополнительного контекста;-
false — элемент не выделен визуально как текущий в наборе связанных элементов.Назначение
aria-current — программно передать визуальное выделение элемента. При этом только один элемент в наборе может быть отмечен как текущий и это нельзя использовать как альтернативу aria-selected и aria-checked.aria-pressed обозначает состояние кнопки-переключателя и используется только на кнопках и элементах с ролью button. Требует реализации механизма зацикленной смены значений при нажатии. Принимает следующие значения:-
true — кнопка нажата;-
false — кнопка не нажата;-
mixed — кнопка зависит от смешанного состояния нескольких других кнопок;-
undefined — кнопка не работает как переключатель.Таким образом все четыре атрибута хоть и обозначают некоторое текущее состояние элемента, но отличаются по смыслу и применимости. Краткая сводка:
-
aria-selected — состояние выбора для option, treeitem, gridcell, row и tab, рекомендуется для одиночного выбора в случае с option и treeitem;-
aria-checked — состояние отметки для checkbox, radio, switch, option, treeitem, menuitemradio и menuitemcheckbox, рекомендуется для множественного выбора в случае с option и treeitem, может быть в смешанном состоянии mixed у checkbox, option, treeitem и menuitemcheckbox;-
aria-current — визуально выделенный элемент в наборе связанных страниц, шагов, локаций, дат, времени или других элементов, один на весь набор;-
aria-pressed — состояние кнопки-переключателя, применимо только для кнопок, может быть в смешанном состоянии mixed.#a11y
👍12❤3🔥2🌚1👨💻1
Настоящий mobile-first
Mobile-first многим известен как подход к вёрстке, при котором сначала реализуется версия для мобильных и расширяется до десктопа. Это противоположность подходу desktop-first, при котором вёрстка идёт от десктопа к мобильным.
Разница обычно сводится к организации медиа-запросов и использованию
Принципиальной разницы нет. В теории, движение от малых экранов к большим даст в итоге чуть меньше стилей, потому что контент по умолчанию mobile-first, адаптируется под ширину экрана и идёт в потоке сверху вниз.
Однако сам термин mobile-first говорит о том, что подход ориентирован в первую очередь на мобильные устройства. Суть не в том, в какую сторону переопределяются стили, а в том, чтобы учесть ограничения мобильных устройств.
Ограничения исходят из конструктивных особенностей. Мобильные устройства компактные и переносимые, питаются от аккумулятора, работают в беспроводных сетях, управляются касаниями и жестами, вмещают меньше контента на экране.
Размеры и питание от аккумулятора не позволяют использовать более мощное железо и массивные системы охлаждения. Поэтому мобильные устройства уступают десктопам по производительности, что повышает требования к оптимизации.
Точки Wi-Fi и мобильные сети менее стабильны, чем проводные соединения. Скорость приёма/передачи, потери пакетов, задержки и другие характеристики сети на мобильных устройствах, как правило, уступают десктопам.
Не смотря на безлимитные тарифы, всё ещё достаточно распространены тарифы с лимитированным трафиком и скоростью. Покрытие сети вне крупных городов ухудшается. Может быть включен режим экономии трафика или батареи.
Отличаются сценарии взаимодействия. Нет мыши и курсора, виртуальная клавиатура на треть экрана заменяет физическую, управление осуществляется жестами, касаниями и долгими нажатиями вместо кликов и наведения указателя мыши.
Настоящий mobile-first — это разработка сайтов и веб-приложений с учётом всех особенностей и ограничений мобильных устройств. Он затрагивает архитектуру проекта и выбор инструментов разработки, а не только направление медиа-запросов.
В хорошем mobile-first:
- Элементы управления и контент компактно и логично размещены на ограниченном по размеру экране, интерфейс не перегружен;
- Интерактивные элементы достаточно большие для взаимодействия касаниями и расположены так, что с ними удобно работать;
- Ресурсы оптимизированы для минимального размера и быстрой загрузки;
- Видео, анимации, сложные фоновые вычисления и сетевые операции ограничены, если мало заряда батареи или включен энергосберегающий режим;
- Упрощённая версия без лишних ресурсов загружается, если включен режим экономии трафика;
- Контент кэшируется на устройстве и доступен оффлайн при потере соединения;
- Контент адаптируется к изменению ориентации экрана, режиму разделения экрана и другим возможностям устройства;
- Сайт использует аппаратные возможности устройства (камеру, микрофон, Bluetooth, акселерометр и другие), если это уместно и помогает пользователю;
#css #ux #performance
Mobile-first многим известен как подход к вёрстке, при котором сначала реализуется версия для мобильных и расширяется до десктопа. Это противоположность подходу desktop-first, при котором вёрстка идёт от десктопа к мобильным.
Разница обычно сводится к организации медиа-запросов и использованию
min-width/max-width. Сначала применяются мобильные стили и переопределяются на более широких экранах, или десктопные переопределяются на более узких./* Mobile-first */
.product-grid {
--col: 1;
--gap: 12px;
display: grid;
grid-template-columns:
repeat(var(--col), minmax(0, 1fr))
;
gap: var(--gap);
}
@media (min-width: 600px) {
.product-grid {
--col: 2;
--gap: 18px;
}
}
@media (min-width: 900px) {
.product-grid {
--col: 3;
--gap: 24px;
}
}
@media (min-width: 1200px) {
.product-grid {
--col: 4;
}
}
/* Desktop-first */
.product-grid {
--col: 4;
--gap: 24px;
display: grid;
grid-template-columns:
repeat(var(--col), minmax(0, 1fr))
;
gap: var(--gap);
}
@media (max-width: 1200px) {
.product-grid {
--col: 3;
}
}
@media (max-width: 900px) {
.product-grid {
--col: 2;
--gap: 18px;
}
}
@media (max-width: 600px) {
.product-grid {
--col: 1;
--gap: 12px;
}
}
Принципиальной разницы нет. В теории, движение от малых экранов к большим даст в итоге чуть меньше стилей, потому что контент по умолчанию mobile-first, адаптируется под ширину экрана и идёт в потоке сверху вниз.
Однако сам термин mobile-first говорит о том, что подход ориентирован в первую очередь на мобильные устройства. Суть не в том, в какую сторону переопределяются стили, а в том, чтобы учесть ограничения мобильных устройств.
Ограничения исходят из конструктивных особенностей. Мобильные устройства компактные и переносимые, питаются от аккумулятора, работают в беспроводных сетях, управляются касаниями и жестами, вмещают меньше контента на экране.
Размеры и питание от аккумулятора не позволяют использовать более мощное железо и массивные системы охлаждения. Поэтому мобильные устройства уступают десктопам по производительности, что повышает требования к оптимизации.
Точки Wi-Fi и мобильные сети менее стабильны, чем проводные соединения. Скорость приёма/передачи, потери пакетов, задержки и другие характеристики сети на мобильных устройствах, как правило, уступают десктопам.
Не смотря на безлимитные тарифы, всё ещё достаточно распространены тарифы с лимитированным трафиком и скоростью. Покрытие сети вне крупных городов ухудшается. Может быть включен режим экономии трафика или батареи.
Отличаются сценарии взаимодействия. Нет мыши и курсора, виртуальная клавиатура на треть экрана заменяет физическую, управление осуществляется жестами, касаниями и долгими нажатиями вместо кликов и наведения указателя мыши.
Настоящий mobile-first — это разработка сайтов и веб-приложений с учётом всех особенностей и ограничений мобильных устройств. Он затрагивает архитектуру проекта и выбор инструментов разработки, а не только направление медиа-запросов.
В хорошем mobile-first:
- Элементы управления и контент компактно и логично размещены на ограниченном по размеру экране, интерфейс не перегружен;
- Интерактивные элементы достаточно большие для взаимодействия касаниями и расположены так, что с ними удобно работать;
- Ресурсы оптимизированы для минимального размера и быстрой загрузки;
- Видео, анимации, сложные фоновые вычисления и сетевые операции ограничены, если мало заряда батареи или включен энергосберегающий режим;
- Упрощённая версия без лишних ресурсов загружается, если включен режим экономии трафика;
- Контент кэшируется на устройстве и доступен оффлайн при потере соединения;
- Контент адаптируется к изменению ориентации экрана, режиму разделения экрана и другим возможностям устройства;
- Сайт использует аппаратные возможности устройства (камеру, микрофон, Bluetooth, акселерометр и другие), если это уместно и помогает пользователю;
#css #ux #performance
❤8👍3😈2🌚1
Страница на Claude Code и Figma MCP
Недавно посмотрел страницу «Coming Soon» одного проекта, которая создана с помощью Claude Code в сочетании с Figma MCP по отрисованному макету. Её создал человек без опыта разработки за 30 минут. На доработку ему понадобилось 3 промпта.
Сама страница — фоновое изображение, логотип, заголовок, текст, поле для email, кнопка отправки и ещё один логотип. То есть простая страница. С визуальной точки зрения всё неплохо: выглядит как надо, адаптивность есть, форма работает.
Я бы не писал об этом, если бы вновь не пришлось узреть мощь современных технологий. Страница создана на Next и Tailwind. Дело не в самих технологиях, а в том, что их использование не оправдано для такой простой страницы.
Агент выбрал в качестве стэка по умолчанию Next и Tailwind, потому что ему не было указано иное. Уж не знаю, почему они делают такой выбор, но это печально. По всей видимости, статистически самый частый вариант. Получается стрельба из пушки по воробьям.
Интересно то, что Pagespeed выдаёт 100 баллов по производительности и 97 по доступности. То есть всё в порядке, цифры зелёные не смотря на Next. Тут важна трактовка результатов. Было бы странно видеть на такой странице не 100.
Достаточно добавить разделы с формой, каруселью, раскрываемыми FAQ, шапку с выпадающим меню, эффекты и аналитику, и эти 100 баллов стремительно полетят вниз. Весь бюджет JS съеден обвязкой Next уже на самом старте.
На страницу загружается 8 JS-файлов общим размером 160кб (~540кб без сжатия) просто потому что так работает Next. Вся интерактивность на странице — отправка email с формы в сторонний сервис. Для этого не нужен Next.
При загрузке страницы виден прыжок шрифта. Подключается вариативный шрифт размером 1.9мб (4.9мб без сжатия) для отрисовки заголовка и блока текста с одним предложением. Обший размер всех ресурсов — 2.5мб (6мб без сжатия).
Для создания этой простейшей страницы развёрнута целая машинерия. Банальная замена текста — процесс с запросом к Claude, который ждёт сборку и загрузку на Vercel. А ведь можно было просто открыть файл и поправить текст.
С точки зрения использования ИИ это тоже расточительство. Сколько лишней работы, токенов и времени затрачено на генерацию конфигов, создание структуры проекта, установку модулей, создание компонентов и генерацию бойлерплейта.
Эта страница должна быть одним HTML-файлом со встроенными
Это пост не о том, что Claude плохой, а о том, что по умолчанию результат выходит посредственный. Нужна экспертиза и понимание, чтобы задавать правильный вектор: стэк, правила, ограничения и желаемый результат.
А ещё настораживает, что кодогенерацией занимаются специалисты без опыта в разработке и на выходе выдают такие вот «сайты». Наверно, всё же, стоит отдавать эту работу разработчикам, чтобы не вышла «мощь современных технологий».
#performance
Недавно посмотрел страницу «Coming Soon» одного проекта, которая создана с помощью Claude Code в сочетании с Figma MCP по отрисованному макету. Её создал человек без опыта разработки за 30 минут. На доработку ему понадобилось 3 промпта.
Сама страница — фоновое изображение, логотип, заголовок, текст, поле для email, кнопка отправки и ещё один логотип. То есть простая страница. С визуальной точки зрения всё неплохо: выглядит как надо, адаптивность есть, форма работает.
Я бы не писал об этом, если бы вновь не пришлось узреть мощь современных технологий. Страница создана на Next и Tailwind. Дело не в самих технологиях, а в том, что их использование не оправдано для такой простой страницы.
Агент выбрал в качестве стэка по умолчанию Next и Tailwind, потому что ему не было указано иное. Уж не знаю, почему они делают такой выбор, но это печально. По всей видимости, статистически самый частый вариант. Получается стрельба из пушки по воробьям.
Интересно то, что Pagespeed выдаёт 100 баллов по производительности и 97 по доступности. То есть всё в порядке, цифры зелёные не смотря на Next. Тут важна трактовка результатов. Было бы странно видеть на такой странице не 100.
Достаточно добавить разделы с формой, каруселью, раскрываемыми FAQ, шапку с выпадающим меню, эффекты и аналитику, и эти 100 баллов стремительно полетят вниз. Весь бюджет JS съеден обвязкой Next уже на самом старте.
На страницу загружается 8 JS-файлов общим размером 160кб (~540кб без сжатия) просто потому что так работает Next. Вся интерактивность на странице — отправка email с формы в сторонний сервис. Для этого не нужен Next.
При загрузке страницы виден прыжок шрифта. Подключается вариативный шрифт размером 1.9мб (4.9мб без сжатия) для отрисовки заголовка и блока текста с одним предложением. Обший размер всех ресурсов — 2.5мб (6мб без сжатия).
Для создания этой простейшей страницы развёрнута целая машинерия. Банальная замена текста — процесс с запросом к Claude, который ждёт сборку и загрузку на Vercel. А ведь можно было просто открыть файл и поправить текст.
С точки зрения использования ИИ это тоже расточительство. Сколько лишней работы, токенов и времени затрачено на генерацию конфигов, создание структуры проекта, установку модулей, создание компонентов и генерацию бойлерплейта.
Эта страница должна быть одним HTML-файлом со встроенными
<style> и <script>. Без Next, Tailwind, node_modules, Turbopack, 8 чанков JS, вариативного шрифта и так далее. Для отправки формы простой скрипт на чистом JS.Это пост не о том, что Claude плохой, а о том, что по умолчанию результат выходит посредственный. Нужна экспертиза и понимание, чтобы задавать правильный вектор: стэк, правила, ограничения и желаемый результат.
А ещё настораживает, что кодогенерацией занимаются специалисты без опыта в разработке и на выходе выдают такие вот «сайты». Наверно, всё же, стоит отдавать эту работу разработчикам, чтобы не вышла «мощь современных технологий».
#performance
🔥16❤7🤡4👍3🌚1😎1
Оптимизация размера DOM бесполезна?
Я писал про уменьшение размера DOM. На днях смотрел подкаст «Организованное Программирование» про SEO, там гость заявил, что считает совет Lighthouse об оптимизации размера DOM вредным и бесполезным. Так ли это на самом деле?
Загрузка любого сайта начинается с получения HTML-разметки. HTML — это текстовый формат. Больше текста = больше размер файла, который нужно передать по сети. Значит файл будет дольше загружаться, что логично.
Но есть парадокс под названием сжатие. 72% текстовых файлов передаются по сети в сжатом виде. Если вы входите в 28%, то настройте хотя-бы Gzip, а лучше Brotli или Zstd. Сервер сжимает файл при отправке, браузер разжимает при получении.
Более тяжёлый в несжатом виде файл может весить меньше более лёгкого файла, если сравнить их размеры в сжатом виде. Алгоритмы работают на повторяющихся фрагментах текста, поэтому на большом HTML они могут быть эффективнее.
Не всегда рост размера HTML приводит к росту размера файла, передаваемого в итоге по сети. Иногда даже наоборот. Выходит, что оптимизация размера HTML пустая трата времени и бесполезный совет? Отнюдь нет.
Помимо передачи по сети HTML служит основой для построения DOM. HTML-парсер проходится по разметке и создаёт для каждого HTML-элемента, атрибута, строки текста и комментария объект с множеством свойств и связей.
Эти объекты нужны для того, чтобы ими манипулировать через DOM API, что под капотом делают любые JS-фреймворки. Также нужно построить CSSOM — для каждого узла вычислить все CSS-свойства, чтобы знать размеры и положение.
CSSOM нужен для итоговых процессов отрисовки страницы: Render tree, Layout и Paint. Это чтобы первично отрисовать страницу. Далее она прокручивается, меню выпадает, слайды переключаются, кнопки меняют цвет при наведении и так далее.
Всё это приводит к повторным пересчётам. Многие взаимодействия со страницей вызывают пересчёт. Браузеры выполняют огромное количество операций в секунду. За годы существования все эти процессы отлично оптимизированы.
Чтобы страница ощущалась быстрой и плавной, все операции по пересчёту стилей и отрисовке должны укладываться в один кадр отрисовки, то есть ~16мс для экрана с частотой обновления 60 Гц. Желательно не впритык, а с некоторым запасом.
Чем больше DOM-узлов, тем больше всего браузеру нужно рассчитать и подготовить к отрисовке. Осложняют дело «тяжёлые» новинки, такие как селектор
JS-отрисовка добавляет дополнительные накладные расходы. Размеры бандлов растут из-за шаблонов в коде, потребление памяти и процессора растёт, потому что код шаблона нужно выполнить, а с VDOM ещё держать в памяти деревья.
С большим DOM можно выйти за пределы одного кадра отрисовки, тогда начнётся заметная потеря кадров, сопровождаемая «лагами» и «фризами». Особо заметно это на низко- и средне-бюджетных смартфонах, которыми пользуется большинство.
Столкнувшись с «фризами» пользователи уйдут к конкурентам, у которых такого нет. Поисковики эти сигналы считывают и запоминают, ухудшаются поведенческие факторы и сайт теряет позиции в выдаче поиска. Бизнес теряет пользователей.
Это может показаться притянутым за уши. Но проблема точно реальная и с ней борются. Глянуть сайт на предмет просадки кадров точно стоит (в DevTools меню с тремя точками → More tools → Rendering → флажок Frame Rendering States).
Во вкладке Performance можно обратить внимание, сколько времени занимает Parse HTML, Rendering и Painting. Во вкладке Memory можно сделать снэпшот и увидеть, сколько оперативной памяти выделено на разные объекты, в том числе узлы DOM.
Экономия на спичках. Возможно и так, учитывая сложность оптимизации HTML. Если дело дошло до этого, значит всё остальное уже хорошо оптимизировано. Тем не менее, я считаю, что верстать нужно с мыслью об экономии узлов.
Современный CSS с flex и grid, а также немного смекалки позволяют достигать результата с меньшим количеством разметки. Убрали лишние узлы, сжали картинки, взяли встроенное API вместо JS и уже немало сэкономили.
#html #performance
Я писал про уменьшение размера DOM. На днях смотрел подкаст «Организованное Программирование» про SEO, там гость заявил, что считает совет Lighthouse об оптимизации размера DOM вредным и бесполезным. Так ли это на самом деле?
Загрузка любого сайта начинается с получения HTML-разметки. HTML — это текстовый формат. Больше текста = больше размер файла, который нужно передать по сети. Значит файл будет дольше загружаться, что логично.
Но есть парадокс под названием сжатие. 72% текстовых файлов передаются по сети в сжатом виде. Если вы входите в 28%, то настройте хотя-бы Gzip, а лучше Brotli или Zstd. Сервер сжимает файл при отправке, браузер разжимает при получении.
Более тяжёлый в несжатом виде файл может весить меньше более лёгкого файла, если сравнить их размеры в сжатом виде. Алгоритмы работают на повторяющихся фрагментах текста, поэтому на большом HTML они могут быть эффективнее.
Не всегда рост размера HTML приводит к росту размера файла, передаваемого в итоге по сети. Иногда даже наоборот. Выходит, что оптимизация размера HTML пустая трата времени и бесполезный совет? Отнюдь нет.
Помимо передачи по сети HTML служит основой для построения DOM. HTML-парсер проходится по разметке и создаёт для каждого HTML-элемента, атрибута, строки текста и комментария объект с множеством свойств и связей.
Эти объекты нужны для того, чтобы ими манипулировать через DOM API, что под капотом делают любые JS-фреймворки. Также нужно построить CSSOM — для каждого узла вычислить все CSS-свойства, чтобы знать размеры и положение.
CSSOM нужен для итоговых процессов отрисовки страницы: Render tree, Layout и Paint. Это чтобы первично отрисовать страницу. Далее она прокручивается, меню выпадает, слайды переключаются, кнопки меняют цвет при наведении и так далее.
Всё это приводит к повторным пересчётам. Многие взаимодействия со страницей вызывают пересчёт. Браузеры выполняют огромное количество операций в секунду. За годы существования все эти процессы отлично оптимизированы.
Чтобы страница ощущалась быстрой и плавной, все операции по пересчёту стилей и отрисовке должны укладываться в один кадр отрисовки, то есть ~16мс для экрана с частотой обновления 60 Гц. Желательно не впритык, а с некоторым запасом.
Чем больше DOM-узлов, тем больше всего браузеру нужно рассчитать и подготовить к отрисовке. Осложняют дело «тяжёлые» новинки, такие как селектор
:has(), контейнерные и стилевые запросы, @scope, каскадные слои.JS-отрисовка добавляет дополнительные накладные расходы. Размеры бандлов растут из-за шаблонов в коде, потребление памяти и процессора растёт, потому что код шаблона нужно выполнить, а с VDOM ещё держать в памяти деревья.
С большим DOM можно выйти за пределы одного кадра отрисовки, тогда начнётся заметная потеря кадров, сопровождаемая «лагами» и «фризами». Особо заметно это на низко- и средне-бюджетных смартфонах, которыми пользуется большинство.
Столкнувшись с «фризами» пользователи уйдут к конкурентам, у которых такого нет. Поисковики эти сигналы считывают и запоминают, ухудшаются поведенческие факторы и сайт теряет позиции в выдаче поиска. Бизнес теряет пользователей.
Это может показаться притянутым за уши. Но проблема точно реальная и с ней борются. Глянуть сайт на предмет просадки кадров точно стоит (в DevTools меню с тремя точками → More tools → Rendering → флажок Frame Rendering States).
Во вкладке Performance можно обратить внимание, сколько времени занимает Parse HTML, Rendering и Painting. Во вкладке Memory можно сделать снэпшот и увидеть, сколько оперативной памяти выделено на разные объекты, в том числе узлы DOM.
Экономия на спичках. Возможно и так, учитывая сложность оптимизации HTML. Если дело дошло до этого, значит всё остальное уже хорошо оптимизировано. Тем не менее, я считаю, что верстать нужно с мыслью об экономии узлов.
Современный CSS с flex и grid, а также немного смекалки позволяют достигать результата с меньшим количеством разметки. Убрали лишние узлы, сжали картинки, взяли встроенное API вместо JS и уже немало сэкономили.
#html #performance
🔥11👍8❤2🌚1🤝1
Стилизуемый combobox и фильтруемый select
Браузеры совместно с OpenUI продолжают развивать
На конференции BlinkOn 21 контрибьютор движка Chromium поделился прогрессом в этом направлении. Я уже писал о том, как работают атрибуты size и multiple у стандартного
Первое — обёртки
Для состояния, когда не выбрана ни одна опция, а значит
Далее продемонстрирован пример создания виджета выпадающего списка опций с возможностью фильтрации через поле ввода. В качестве образца выступает виджет добавления тегов в GitHub.
Виджет собран из нескольких встроенных API. Кнопка с атрибутами
Прорабатывается вариант для простых случаев, когда есть только опции и поле для их фильтрации, без дополнительных элементов. В таком случае предлагается вкладывать
К фильтрации предусмотрено событие
Показана возможность стилизации уже существующей в браузерах связки
Некоторые из показанных возможностей тестируются и уже доступны в Chrome за флагом экспериментальных технологий. Разработчики собирают обратную связь, обсуждают спорные моменты и дорабатывают API.
#html #css #ui
Браузеры совместно с OpenUI продолжают развивать
<select>, добавляя новые функции и возможности стилизации. В Сhrome уже можно стилизовать стандартный <select> с одиночным выбором, на подходе вариант с множественным выбором и combobox.На конференции BlinkOn 21 контрибьютор движка Chromium поделился прогрессом в этом направлении. Я уже писал о том, как работают атрибуты size и multiple у стандартного
<select> и планах по расширению их функциональности.<select multiple size="1">
<button>
<selectedcontent>
<div>One</div>
<div>Two</div>
</selectedcontent>
<span>0 Selected</span>
</button>
<option selected>One</option>
<option selected>Two</option>
<!-- ... -->
</select>
<style>
selectedcontent:not(:empty) + span {
display: none;
}
</style>
Первое — обёртки
<div> для проецируемых опций в <selectedcontent>. Этот элемент был внедрён как часть стилизуемого <select> для проецирования значения выбранной опции. Теперь проецируются несколько опций и они оборачиваются в <div> для стилизации.Для состояния, когда не выбрана ни одна опция, а значит
<selectedcontent> пуст, предлагается использовать резервный элемент <span> с текстом. Он скрывается через комбинацию псевдо-классов :not(), :empty и комбинатор +.Далее продемонстрирован пример создания виджета выпадающего списка опций с возможностью фильтрации через поле ввода. В качестве образца выступает виджет добавления тегов в GitHub.
<button
commandfor="dialog"
command="showpopover"
>
<selectedcontent id="sc">
</selectedcontent>
</button>
<dialog popover id="dialog">
<input filter="select">
<select
size="4"
id="select"
selectedcontentelement="sc"
>
<!-- опции -->
</select>
<!-- можно добавить другие элементы -->
</dialog>
Виджет собран из нескольких встроенных API. Кнопка с атрибутами
command/commandfor управляет отображением диалога, который реализован с помощью <dialog popover>. Внутри <select>, который связан с <selectedcontent> для проекции выбранной опции.<input> связан с <select> через новый атрибут filter, который позволяет фильтровать опции. Предложенный вариант многословен, но хорош тем, что в <dialog> можно поместить другие элементы (текст, кнопки, иконки) помимо <input> и <select>.Прорабатывается вариант для простых случаев, когда есть только опции и поле для их фильтрации, без дополнительных элементов. В таком случае предлагается вкладывать
<input> внутрь <select> перед опциями. Для этого будет доработан парсер.<select>
<input>
<!-- опции -->
</select>
К фильтрации предусмотрено событие
beforefilter, которое можно перехватить, отменить стандартное поведение через preventDefault(). Это механизм для реализации подгрузки данных из внешнего источника и динамической генерации списка опций.Показана возможность стилизации уже существующей в браузерах связки
<input> и <datalist>. Как и в случае со стилизуемым <select>, API базируется на идее базового внешнего вида и стандартных стилей, задаваемых свойством appearance: base;.<input list="options">
<datalist id="options">
<!-- опции -->
</datalist>
<style>
input[list], datalist {
appearance: base;
}
</style>
Некоторые из показанных возможностей тестируются и уже доступны в Chrome за флагом экспериментальных технологий. Разработчики собирают обратную связь, обсуждают спорные моменты и дорабатывают API.
#html #css #ui
YouTube
Customizable combobox and filterable select [BlinkOn 21]
Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.
👍6❤1🌚1🤗1
You don't know HTML: <fieldset>
Элемент
Подпись задаётся с помощью элемента
У элемента
Помимо встроенной роли, семантики и привязки имени у
Атрибут
У
Атрибут
У
Таким образом
#ydkhtml
Элемент
<fieldset> в HTML предназначен для группировки элементов формы с опциональной подписью. Явные элементы для группировки — флажки, радио-кнопки, переключатели и данные, которые разбиты на несколько полей, как адрес или телефон.Подпись задаётся с помощью элемента
<legend>. Если он есть, то должен быть первым прямым потоком <fieldset>. Иное размещение или оборачивание в контейнер не валидно и подпись не будет привязана к <fieldset>.У элемента
<fieldset> встроенная роль group. Наличие валидного <legend> задаёт имя для группы. Воспроизвести это можно с помощью ARIA, но зачем, если в платформе есть встроенный элемент с соответствующей семантикой:<div
role="group"
aria-labelledby="legend"
>
<div id="legend">Размер</div>
<!-- переключатели -->
</div>
<!-- встроенный аналог -->
<fieldset>
<legend>Размер</legend>
<!-- переключатели -->
</fieldset>
Помимо встроенной роли, семантики и привязки имени у
<fieldset> есть API. Атрибут disabled отключает вложенные элементы формы, поэтому не нужно вручную каждому проставлять disabled. Полезно для отключения части формы.Атрибут
name задаёт идентификатор группы для доступа к ней через Form API. Это удобно использовать в сочетании со свойством elements, которое хранит все элементы формы или группы. Через него можно получить конкретный элемент.<form name="variants">
<fieldset name="sizes">
<legend>Размер</legend>
<!-- переключатели -->
</fieldset>
<!-- ... -->
</form>
<script>
const variantsForm = document.forms['variants'];
// или document.forms.variants
// или document.forms.namedItem('variants')
const sizeGroup = variantsForm.elements['sizes'];
// или variantsForm.elements.sizes
// или variantsForm.elements.namedItem('sizes')
// отключение группы
sizeGroup.disabled = true;
// элементы группы
const elements = sizeGroup.elements;
</script>
У
<fieldset> можно вызывать методы Constraint Validation API и проверить на валидность только поля из группы, а не всей формы целиком. Также применимы псевдо-классы :valid/:invalid, :user-valid/:user-invalid.Атрибут
form позволяет привязать группу со всеми элементами к указанной форме. Это позволяет вынести группу за пределы формы, сохранив с ней связь. Сбор данных для отправки, валидация и методы работы с элементами будут доступны.У
<fieldset> есть некоторые особенности стилизации. По умолчанию у него блочный контекст форматирования, ширина подстраивается под контент, есть рамка и <legend> размещается поверх рамки. Но элемент полностью стилизуемый.Таким образом
<fieldset> в сочетании с <legend> полезен для группировки полей, передаёт вспомогательным технологиям нужную семантику и имя, обладает API для управления элементами (отключение, вынос из формы, получение, валидация).#ydkhtml
👍12🌚1🤝1
sizes="auto" для изображений
Для адаптивных изображений у элемента
В Firefox 150 и Chrome 124 добавили новое значение
Зачем указывать
Обнаружив изображение, браузер поместит его в очередь загрузки. В моменте нужно решить, какое из изображений ставить в очередь. К этому времени стили могут быть ещё не загружены или не обработаны. Поэтому браузер смотрит значение
С лениво-загружаемыми изображениями ситуация другая. Их загрузка отложена до тех пор, пока изображение не появится в области просмотра. Чтобы это выяснить, браузеру нужно обработать стили и знать размеры и положение на странице.
К моменту загрузки ленивого изображения, даже если оно находится на первом экране, браузер уже обработал стили и знает все размеры. Именно поэтому
Таким образом изображениям с ленивой загрузкой
Синтаксисом предусмотрено совмещение значения
Мэт Маркиз, бывший председатель группы адаптивных изображений (Responsive Image Community Group) написал статью «The end of responsive images», в которой рассказал более чем 10-летнюю историю появления
#html #css
Для адаптивных изображений у элемента
<img> есть два атрибута. srcset задаёт набор изображений с физической шириной или плотностью пикселей. sizes задаёт доступное пространство, которое браузер заполняет подходящим изображением.В Firefox 150 и Chrome 124 добавили новое значение
sizes="auto". Однако не стоит думать, что теперь указывать размеры в sizes не нужно. sizes="auto" работает в паре с loading="lazy". Без него указывать auto нет смысла, работать не будет.Зачем указывать
sizes, разве браузер не знает размеры области для отрисовки изображения? Дело в том, что не знает до загрузки и обработки всех стилей. Сканер предварительной загрузки анализирует HTML и ищет ресурсы.Обнаружив изображение, браузер поместит его в очередь загрузки. В моменте нужно решить, какое из изображений ставить в очередь. К этому времени стили могут быть ещё не загружены или не обработаны. Поэтому браузер смотрит значение
sizes.С лениво-загружаемыми изображениями ситуация другая. Их загрузка отложена до тех пор, пока изображение не появится в области просмотра. Чтобы это выяснить, браузеру нужно обработать стили и знать размеры и положение на странице.
К моменту загрузки ленивого изображения, даже если оно находится на первом экране, браузер уже обработал стили и знает все размеры. Именно поэтому
sizes="auto" будет работать, браузер возьмёт известные ему размеры области.Таким образом изображениям с ленивой загрузкой
loading="lazy" можно задать sizes="auto". Остальным всё ещё нужно указывать размеры. Также остаются браузеры, которые не понимают значение auto, для них тоже нужны размеры.Синтаксисом предусмотрено совмещение значения
auto с размерами. Если браузер не понимает auto или не может получить размеры из стилей, он откатится к размеру, который указан после auto через запятую: sizes="auto, (min-width: 600px) 50vw, 90vw".Мэт Маркиз, бывший председатель группы адаптивных изображений (Responsive Image Community Group) написал статью «The end of responsive images», в которой рассказал более чем 10-летнюю историю появления
sizes="auto".#html #css
Piccalilli
The end of responsive images
Mat Marquis has waited 14 years to write this article. The sizes attribute has been a necessary evil but now, with an auto value capability, it’s completely transformed authoring responsive images on the web.
👍5🔥3🌚1🤝1
ARIA APG: доверяй, но проверяй
Есть ресурс под названием ARIA Authoring Practices Guide, сокращённо APG. На него ссылаются как на источник доступных шаблонов элементов интерфейса. Это неплохой ресурс, но при обращении к нему стоит помнить о некоторых нюансах.
Ресурс выглядит официально, содержит логотип W3C и WAI, размещён на домене w3.org, упоминается на сайте инициативы по веб доступности. Внушает доверие и вызвает ложное ощущение официального стандарта от W3C.
На деле APG — не стандарт W3C, в отличие от ARIA, WCAG, ARIA in HTML и других. APG создан специальной группой APG Task Force из сообщества WAI, которое, в свою очередь, одно из многих сообществ в составе консорциума W3C.
Задача APG — показать, как применять стандарт ARIA для реализации элементов интерфейса. Шаблоны демонстрируют все роли, свойства и состояния в соответствии с правилами стандарта. Это своего рода витрина ARIA.
Если взглянуть на шаблон кнопки, то APG предлагает использовать
Тем временем первое правило ARIA гласит, что не стоит использовать ARIA, если есть встроенный элемент. В HTML кнопка есть —
Аналогично с шаблонами флажков, радио-кнопок, диалогов, раскрываемых блоков, ссылок, ориентиров, шкалы, слайдера, таблиц и так далее. Они показывают, как реализовать с помощью ARIA. Зачастую в этом нет необходимости.
Отдельного внимания заслуживает борьба Адриана Розелли с шаблоном навигации сайта, который долгое время предлагал использовать не подходящие роли меню. Разработчики внедряли этот шаблон на сайты и делали только хуже.
Всё сказанное выше не значит, что на APG не стоит смотреть. Это неплохой источник информации о проектировании доступных интерфейсов. Важно не воспринимать его как официальный источник истины со 100% правильными шаблонами.
Эрик Бэйли считает хорошими частями в APG:
- Названия шаблонов. Хорошо, когда вся команда говорит на одном языке;
- Описания шаблонов. Суть шаблона, для чего нужен, как работает и когда применять;
- Клавиатурная навигация. Клавиши и их сочетания, которые должны работать при взаимодействии;
Остальное вторично. Таблицы поддержки не отражают реальный уровень поддержки, примеры кода не согласованы, написаны в разных стилях, используют устаревшие подходы и не готовы к продакшену, часть шаблонов заменяется встроенным HTML.
Используйте APG как источник знаний о сути того или иного шаблона и навигации с помощью клавиатуры. По возможности используйте встроенные HTML-элементы, обращайтесь к официальному стандарту ARIA и всегда тестируйте.
#ui #a11y
Есть ресурс под названием ARIA Authoring Practices Guide, сокращённо APG. На него ссылаются как на источник доступных шаблонов элементов интерфейса. Это неплохой ресурс, но при обращении к нему стоит помнить о некоторых нюансах.
Ресурс выглядит официально, содержит логотип W3C и WAI, размещён на домене w3.org, упоминается на сайте инициативы по веб доступности. Внушает доверие и вызвает ложное ощущение официального стандарта от W3C.
На деле APG — не стандарт W3C, в отличие от ARIA, WCAG, ARIA in HTML и других. APG создан специальной группой APG Task Force из сообщества WAI, которое, в свою очередь, одно из многих сообществ в составе консорциума W3C.
Задача APG — показать, как применять стандарт ARIA для реализации элементов интерфейса. Шаблоны демонстрируют все роли, свойства и состояния в соответствии с правилами стандарта. Это своего рода витрина ARIA.
Если взглянуть на шаблон кнопки, то APG предлагает использовать
<div>, <a> и <span> с ролью button, tabindex="0" для фокуса и JS для обработки нажатия. APG свою задачу выполнил: показал, как использовать роль button.Тем временем первое правило ARIA гласит, что не стоит использовать ARIA, если есть встроенный элемент. В HTML кнопка есть —
<button>. На практике <div> с ролью кнопки, tabindex и обработчиком нажатий считается антипаттерном.Аналогично с шаблонами флажков, радио-кнопок, диалогов, раскрываемых блоков, ссылок, ориентиров, шкалы, слайдера, таблиц и так далее. Они показывают, как реализовать с помощью ARIA. Зачастую в этом нет необходимости.
Отдельного внимания заслуживает борьба Адриана Розелли с шаблоном навигации сайта, который долгое время предлагал использовать не подходящие роли меню. Разработчики внедряли этот шаблон на сайты и делали только хуже.
Всё сказанное выше не значит, что на APG не стоит смотреть. Это неплохой источник информации о проектировании доступных интерфейсов. Важно не воспринимать его как официальный источник истины со 100% правильными шаблонами.
Эрик Бэйли считает хорошими частями в APG:
- Названия шаблонов. Хорошо, когда вся команда говорит на одном языке;
- Описания шаблонов. Суть шаблона, для чего нужен, как работает и когда применять;
- Клавиатурная навигация. Клавиши и их сочетания, которые должны работать при взаимодействии;
Остальное вторично. Таблицы поддержки не отражают реальный уровень поддержки, примеры кода не согласованы, написаны в разных стилях, используют устаревшие подходы и не готовы к продакшену, часть шаблонов заменяется встроенным HTML.
Используйте APG как источник знаний о сути того или иного шаблона и навигации с помощью клавиатуры. По возможности используйте встроенные HTML-элементы, обращайтесь к официальному стандарту ARIA и всегда тестируйте.
#ui #a11y
1👍6❤4🔥3⚡1🌚1😎1
Переусложнённые радио-кнопки в Shadcn
Пол Геберт в блоге написал о чрезмерно переусложнённых радио-кнопках в Shadcn. Это библиотека готовых компонентов для React, которая построена на базе Radix UI, использует Tailwind и работает по принципу «copy-paste» кода в проект.
Предположим, что в проекте нужны радио-кнопки. В HTML это решается добавлением
Если залезать под капот импортируемого
Радио-кнопка в Shadcn — это кнопка с ARIA-атрибутами для имитации радио-кнопки, SVG-круг, скрытый
Применение
Задумка Shadcn и Radix, по всей видимости, в надёжности стилизации. С
#html #css #ui
Пол Геберт в блоге написал о чрезмерно переусложнённых радио-кнопках в Shadcn. Это библиотека готовых компонентов для React, которая построена на базе Radix UI, использует Tailwind и работает по принципу «copy-paste» кода в проект.
Предположим, что в проекте нужны радио-кнопки. В HTML это решается добавлением
<input type="radio">. В Shadcn для этого нужно 3 импорта, 45 строк кода, сторонняя библиотека иконок для кружка, 30 классов Tailwind.Если залезать под капот импортируемого
RadioGroupPrimitive, там ещё 215 строк кода и 7 импортов. Неужели для радио-кнопок нужно столько кода? Но это ладно. Какой результат получается в браузере при отрисовке этого всего?<button
id="debit"
class="классы Tailwind"
type="button"
role="radio"
aria-checked="true"
data-state="checked"
value="debit"
tabindex="0"
data-radix-collection-item
>
<span
class="классы Tailwind"
data-state="checked"
>
<svg
class="классы Tailwind"
xmlns="..."
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<circle cx="12" cy="12" r="10">
</circle>
</svg>
</span>
</button>
<input
aria-hidden="true"
style="..."
tabindex="-1"
type="radio"
value="debit"
checked
name="credit-or-debit"
>
Радио-кнопка в Shadcn — это кнопка с ARIA-атрибутами для имитации радио-кнопки, SVG-круг, скрытый
<input type="radio">, который нужен для работы форм и классы Tailwind. Всё может быть гораздо проще, если использовать стандартный HTML:<input
type="radio"
name="credit-or-debit"
value="debit"
checked
>
Применение
appearance: none к флажкам и радио-кнопкам сбрасывает их стандартный внешний вид. После этого можно задавать размеры, фон, рамку, тень, закругление и так далее. Маркеры можно сделать при помощи псевдо-элементов.<input
type="radio"
name="credit-or-debit"
value="debit"
checked
>
<style>
input[type="radio"] {
--color: currentColor;
appearance: none;
display: inline-grid;
place-content: center;
width: 24px;
height: 24px;
border: 2px solid var(--color);
border-radius: 50%;
margin: 0;
&::before {
content: '';
width: 12px;
height: 12px;
border-radius: 50%;
background-color: transparent;
transition: background-color .3s;
}
&:checked::before {
background-color: var(--color);
}
@media (forced-colors: active) {
--color: ButtonText;
}
}
</style>
Задумка Shadcn и Radix, по всей видимости, в надёжности стилизации. С
<input> дела обстоят хуже, чем с <button>. Но всё же решение с appearance работает сегодня во всех актуальных браузерах. Тогда к чему весь этот оверинжиниринг?#html #css #ui
Paulmakeswebsites
The Incredible Overcomplexity of the Shadcn Radio Button
Radio buttons are built into web browsers. Why are we using a UI library that wraps another UI library that rebuilds radio buttons from scratch? Why does rendering a radio button require multiple dependencies and several kilobytes of JavaScript? How did we…
🔥11👍5🌚4❤3👨💻1
Маркетинговый сайт, веб-компоненты и nanotags
Павел Гринченко в блоге Злых Марсиан описал способ разработки маркетинговых сайтов с использованием веб-компонентов и разработанного для них инструмента под названием nanotags, в основе которого другое решение от Марсиан — nanostores.
Маркетинговый сайт — это не приложение с тяжёлой логикой и большим количеством интерактивности. Это статический контент с точечными интерактивными элементами. Такие сайты создаются с использованием генераторов статики, в частности Astro.
Остаётся вопрос с тем, как добавлять ту самую интерактивность. Павел считает API веб-компонентов, встроенные в браузеры, полезными для этой задачи. Но в сыром виде API низкоуровневые и многословные. Поэтому была создана библиотека nanotags.
Это лёгкая библиотека, которая добавляет декларативный способ создания пользовательских элементов, поиска узлов, объявления реактивных свойств на основе nanostores и обработки событий. Цель — скрыть шаблонный код под капот.
nanotags рассчитан на работу с готовой разметкой, генерируемой на сервере или при сборке. Шаблонизатор отсутствует, Shadow DOM не используется. Это отличает nanotags от популярной библиотеки для веб-компонентов — Lit.
В разметке пользовательский элемент
Затем подключается nanotags. Функция
В
Библиотека хорошо интегрирована с TypeScript, выводит типы, поддерживает Standard Schema валидаторы (Valibot, Zod, ArkType) для свойств, работает с данными в формате JSON, делает проверки в рантайме на основе схем.
Больше возможностей nanotags описано в документации. Это интересный взгляд на то, как работать с веб-компонентами. Миграция сэкономила 100кб JS, что хорошо и позволяет лучше вписываться в бюджеты производительности.
Также я обратил внимание, что библиотека разработана с уважением к стандарту HTML. Ссылки на элементы отмечаются атрибутом
Маленькая деталь, которая, тем не менее, отражает отношение автора к стандартам. Все синтаксические расширения выполнены в соответствии с правилами расширения HTML, без выдуманного синтаксиса с невалидной разметкой. За это от меня респект.
#js #tools
Павел Гринченко в блоге Злых Марсиан описал способ разработки маркетинговых сайтов с использованием веб-компонентов и разработанного для них инструмента под названием nanotags, в основе которого другое решение от Марсиан — nanostores.
Маркетинговый сайт — это не приложение с тяжёлой логикой и большим количеством интерактивности. Это статический контент с точечными интерактивными элементами. Такие сайты создаются с использованием генераторов статики, в частности Astro.
Остаётся вопрос с тем, как добавлять ту самую интерактивность. Павел считает API веб-компонентов, встроенные в браузеры, полезными для этой задачи. Но в сыром виде API низкоуровневые и многословные. Поэтому была создана библиотека nanotags.
Это лёгкая библиотека, которая добавляет декларативный способ создания пользовательских элементов, поиска узлов, объявления реактивных свойств на основе nanostores и обработки событий. Цель — скрыть шаблонный код под капот.
nanotags рассчитан на работу с готовой разметкой, генерируемой на сервере или при сборке. Шаблонизатор отсутствует, Shadow DOM не используется. Это отличает nanotags от популярной библиотеки для веб-компонентов — Lit.
<my-counter count="0">
<span data-ref="display">0</span>
<button data-ref="button">+1</button>
</my-counter>
<script>
import { define } from "nanotags"
define("my-counter")
.withProps(p => ({
count: p.number(0)
}))
.withRefs(r => ({
display: r.one("span"),
button: r.one("button")
}))
.setup(ctx => {
ctx.on(ctx.refs.button, "click", () => {
ctx.props.$count.set(ctx.props.$count.get() + 1)
})
ctx.effect(ctx.props.$count, val => {
ctx.refs.display.textContent = String(val)
})
})
</script>
В разметке пользовательский элемент
<my-counter>, внутри которого <span> и <button>. Разметка генерируется Astro на этапе сборки. Вместо Astro может быть любой генератор статики или серверное решение, которое отдаёт готовый HTML.Затем подключается nanotags. Функция
define() определяет пользовательский элемент. В withProps() указываются реактивные свойства, их тип и начальное значение. В withRefs() задаются ссылки на узлы, которые должны быть в разметке.В
setup() идёт установка обработчиков событий и эффектов, которые меняют значения реактивных свойств. Доступен объект контекста ctx, в котором хранятся свойства, ссылки на узлы и прочая информация о компоненте.Библиотека хорошо интегрирована с TypeScript, выводит типы, поддерживает Standard Schema валидаторы (Valibot, Zod, ArkType) для свойств, работает с данными в формате JSON, делает проверки в рантайме на основе схем.
Больше возможностей nanotags описано в документации. Это интересный взгляд на то, как работать с веб-компонентами. Миграция сэкономила 100кб JS, что хорошо и позволяет лучше вписываться в бюджеты производительности.
Также я обратил внимание, что библиотека разработана с уважением к стандарту HTML. Ссылки на элементы отмечаются атрибутом
data-ref, JSON-данные хранятся в блоках данных, пользовательские элементы названы в соответствии с правилами.Маленькая деталь, которая, тем не менее, отражает отношение автора к стандартам. Все синтаксические расширения выполнены в соответствии с правилами расширения HTML, без выдуманного синтаксиса с невалидной разметкой. За это от меня респект.
#js #tools
evilmartians.com
From React to native web with nanotags: a migration that saved 100 KB—Martian Chronicles, Evil Martians’ team blog
Most marketing sites ship a SPA framework just to toggle a sidebar. Here's how we migrated an Astro site from React and Ark UI to native Web Components: 100 KB less JavaScript, no functionality lost, and a tiny library called nanotags that makes Custom Elements…
🔥3🤔3⚡1❤1
Разработка сайтов, дружелюбных для агентов
ИИ агенты ворвались в нашу жизнь и стали ещё одними потребителями Интернета. В 525 выпуске Веб-стандартов обсуждали статью с web.dev о разработке сайтов, дружелюбных для агентов. Сейчас это набирает популярность.
Агенты взаимодействуют с сайтами одним из трёх способов:
- Анализ скриншота страницы с помощью машинного зрения;
- Анализ HTML-кода страницы и построенного на его основе DOM;
- Анализ дерева доступности, построенного из DOM и CSSOM.
Возможны комбинации этих способов, чтобы разрешить неоднозначные моменты: в разметке может быть кнопка «Добавить в корзину» как
В статье даются советы, которые помогут агентам лучше воспринимать сайт:
- Все действия чётко обозначены в интерфейсе;
- Структура сайта стабильная и консистентная;
- Нет прозрачных наложений поверх интерфейса;
- Структура контента передана с помощью семантического HTML или ARIA, если нет возможности использовать семантический HTML;
- Интерактивные элементы обозначены в CSS с помощью
- Поля формы и подписи к ним связаны через
- Размер интерактивных элементов как минимум 8×8px.
Глядя на эти пункты я понимаю: адаптация сайта для агентов — это просто создание нормального сайт для людей. Все советы были актуальны задолго до бума агентов. Это просто базовые советы как сделать хороший сайт.
Чётко идентифицируемые элементы, стабильная структура, семантический HTML, ARIA для нестандартных виджетов, связь полей с метками, размер элементов, курсор с пальцем и отсутствие наложений — это база при разработке сайтов.
Всё настолько плохо, что теперь это не база, а новая модная дисциплина и навык «адаптация сайта для агентов»? С другой стороны, если это подстегнёт внедрение хороших практик для улучшения сайтов, то почему бы и нет.
Тем, кто всегда стремился к качественным, семантичным, доступным и быстрым сайтам, выбирал готовый HTML и статику вместо SPA и сложных решений — повезло, их сайты уже со старта гораздо лучше адаптированы для агентов.
Стоит сказать, что в рамках Agentic Engine Optimization есть более специфические приёмы, как описывает Эдди Османи. Но они всё равно сводятся к предоставлению краткой выжимки контента, ссылкам и грамотной структуре.
Важно кратко и чётко донести смысл, контент должен быть структурирован с помощью списков и иерархии заголовков, должно быть содержание с кратким описанием и ссылками. То есть всё примерно так же, как и для людей.
#html #css #ui
ИИ агенты ворвались в нашу жизнь и стали ещё одними потребителями Интернета. В 525 выпуске Веб-стандартов обсуждали статью с web.dev о разработке сайтов, дружелюбных для агентов. Сейчас это набирает популярность.
Агенты взаимодействуют с сайтами одним из трёх способов:
- Анализ скриншота страницы с помощью машинного зрения;
- Анализ HTML-кода страницы и построенного на его основе DOM;
- Анализ дерева доступности, построенного из DOM и CSSOM.
Возможны комбинации этих способов, чтобы разрешить неоднозначные моменты: в разметке может быть кнопка «Добавить в корзину» как
<div>, но на скриншоте она будет выглядеть как кнопка, а JS добавит необходимое поведение (не делайте так).В статье даются советы, которые помогут агентам лучше воспринимать сайт:
- Все действия чётко обозначены в интерфейсе;
- Структура сайта стабильная и консистентная;
- Нет прозрачных наложений поверх интерфейса;
- Структура контента передана с помощью семантического HTML или ARIA, если нет возможности использовать семантический HTML;
- Интерактивные элементы обозначены в CSS с помощью
cursor: pointer;- Поля формы и подписи к ним связаны через
<label for="...">;- Размер интерактивных элементов как минимум 8×8px.
Глядя на эти пункты я понимаю: адаптация сайта для агентов — это просто создание нормального сайт для людей. Все советы были актуальны задолго до бума агентов. Это просто базовые советы как сделать хороший сайт.
Чётко идентифицируемые элементы, стабильная структура, семантический HTML, ARIA для нестандартных виджетов, связь полей с метками, размер элементов, курсор с пальцем и отсутствие наложений — это база при разработке сайтов.
Всё настолько плохо, что теперь это не база, а новая модная дисциплина и навык «адаптация сайта для агентов»? С другой стороны, если это подстегнёт внедрение хороших практик для улучшения сайтов, то почему бы и нет.
Тем, кто всегда стремился к качественным, семантичным, доступным и быстрым сайтам, выбирал готовый HTML и статику вместо SPA и сложных решений — повезло, их сайты уже со старта гораздо лучше адаптированы для агентов.
Стоит сказать, что в рамках Agentic Engine Optimization есть более специфические приёмы, как описывает Эдди Османи. Но они всё равно сводятся к предоставлению краткой выжимки контента, ссылкам и грамотной структуре.
Важно кратко и чётко донести смысл, контент должен быть структурирован с помощью списков и иерархии заголовков, должно быть содержание с кратким описанием и ссылками. То есть всё примерно так же, как и для людей.
#html #css #ui
❤7👍4😁1🤔1
15й Всемирный День Осведомлённости о Доступности
Сегодня, 21 мая 2026 — всемирный день осведомлённости о доступности (Global Accessibility Awareness Day — GAAD). Это отличный повод напомнить о важности доступности и поделиться материалами на эту тему.
Я регулярно пишу в канале разные посты на тему доступности в вебе и отмечаю эти посты тегом #a11y@alexnozer_dev. К сожалению, теги в канале появились не сразу, поэтому часть материалов о доступности не помечена.
В конце марта вышел ежегодный отчёт The WebAIM Million с результатами анализа доступности миллиона сайтов с помощью инструмента WAVE. Также данные о состоянии доступности можно найти в отчёте Web Almanac 2025 от HttpArchive.
По итогам WebAIM 2026 в топе проблем из года в год один и те же, только некоторые пункты меняются местами. В этом году список такой:
- Недостаточный уровень контрастности текста на 83.9% сайтов;
- Отсутствующий альтернативный текст у изображений на 53.1% сайтов;
- Отсутствующие подписи у полей ввода на 51% сайтов;
- Пустые ссылки на 46.3% сайтов;
- Пустые кнопки на 30.6% сайтов;
- Отсутствующий язык документа на 13.5% сайтов.
Это лишь автоматически обнаруживаемые проблемы. Часть проблем не может быть обнаружена автоматическими средствами анализа. По каждой проблеме из топа планирую сделать отдельный пост, их не сложно исправить.
Есть папки с телеграм-каналами о доступности, собранные Верой Шингарёвой:
- Accessibility-папка — каналы, которые пишут про доступность или около;
- a11y_person — блоги людей с инвалидностью и без, которые пишут про доступность, инклюзию свою жизнь;
- a11y_org — организации в сфере доступности и инклюзии.
У Стаса Мельникова есть интересная серия статей про HTML и CSS ошибки, которые влияют на доступность (вся серия доступна по тегу #html_css_a11y_story_melnik909). Стас вместе со своим знакомым Ильёй, незрячим человеком, делятся распространёнными ошибками и как их исправить.
#a11y
Сегодня, 21 мая 2026 — всемирный день осведомлённости о доступности (Global Accessibility Awareness Day — GAAD). Это отличный повод напомнить о важности доступности и поделиться материалами на эту тему.
Я регулярно пишу в канале разные посты на тему доступности в вебе и отмечаю эти посты тегом #a11y@alexnozer_dev. К сожалению, теги в канале появились не сразу, поэтому часть материалов о доступности не помечена.
В конце марта вышел ежегодный отчёт The WebAIM Million с результатами анализа доступности миллиона сайтов с помощью инструмента WAVE. Также данные о состоянии доступности можно найти в отчёте Web Almanac 2025 от HttpArchive.
По итогам WebAIM 2026 в топе проблем из года в год один и те же, только некоторые пункты меняются местами. В этом году список такой:
- Недостаточный уровень контрастности текста на 83.9% сайтов;
- Отсутствующий альтернативный текст у изображений на 53.1% сайтов;
- Отсутствующие подписи у полей ввода на 51% сайтов;
- Пустые ссылки на 46.3% сайтов;
- Пустые кнопки на 30.6% сайтов;
- Отсутствующий язык документа на 13.5% сайтов.
Это лишь автоматически обнаруживаемые проблемы. Часть проблем не может быть обнаружена автоматическими средствами анализа. По каждой проблеме из топа планирую сделать отдельный пост, их не сложно исправить.
Есть папки с телеграм-каналами о доступности, собранные Верой Шингарёвой:
- Accessibility-папка — каналы, которые пишут про доступность или около;
- a11y_person — блоги людей с инвалидностью и без, которые пишут про доступность, инклюзию свою жизнь;
- a11y_org — организации в сфере доступности и инклюзии.
У Стаса Мельникова есть интересная серия статей про HTML и CSS ошибки, которые влияют на доступность (вся серия доступна по тегу #html_css_a11y_story_melnik909). Стас вместе со своим знакомым Ильёй, незрячим человеком, делятся распространёнными ошибками и как их исправить.
#a11y
1🔥4❤1🥰1🎉1
Недостаточный уровень контрастности текста
Контрастность определяет соотношение между цветом текста и цветом фона, что влияет на читаемость, утомляемость глаз и способность визуального восприятия контента людьми с нарушениями зрения. Это самая частая проблема доступности по данным WebAIM.
Существует два алгоритма измерения контрастности: WCAG и APCA. Первый существует с момента появления стандарта WCAG и используется во всех текущих версиях стандарта, но даёт ложно-позитивные результаты для некоторых сочетаний цветов.
APCA более новый и надёжный алгоритм. Он учитывает восприятие человеческого глаза, поэтому более точно отражает контрастность. APCA заменит текущий алгоритм в стандарте WCAG 3, а пока массовым остаётся старый алгоритм WCAG.
Есть 3 критерия WCAG, которые затрагивают контрастность:
- 1.4.3 Contrast (Minimum);
- 1.4.6 Contrast (Enhanced);
- 1.4.11 Non-text Contrast.
Я сосредоточусь на 1.4.3. Потому что 1.4.6 выдвигает повышенные требования и исходит из того, что 1.4.3 удовлетворён. А 1.4.11 рассматривает нетекстовый контент, там иные требования и эта проблема не входит в топ самых распространённых.
Критерий 1.4.3 выдвигает следующие требования к уровню контрастности текста:
- 4.5:1 для текста размером до 24px или полужирного текста размером до 19px;
- 3:1 для текста размером от 24px или полужирного текста размером от 19px.
Проблема со стороны разработчиков, которые задают цвета в CSS, в том, что они получают от дизайнеров готовые макеты. Какие цветам там есть, такие переносятся в код. То есть контрастность текста — зона ответственности дизайнеров.
Поэтому исправление проблемы стоит начать с дизайна: установить требования и добавить в чеклист проверки. Инициатива может исходить и от разработки на этапе передачи макета в виде комментариев о недостаточной контрастности.
Для проверки контрастности текста в Figma есть плагины. Я пользуюсь плагином Contrast, но есть много других. Также рекомендую Polychrome, хоть он и работает по алгоритму APCA, он точнее отражает реальный уровень контрастности.
Если продукт большой, над ним работают несколько команд и есть дизайн-система, то проблему контрастности стоит решать на уровне дизайн-системы. Проверить палитру, гайды по использованию цветов, модули типографики.
А если это маленький проект, дизайнер сдал макет, получил оплату и ушёл? Частое явление в заказной разработке сайтов. Тут я предлагаю брать ситуацию в свои руки и отходить от цветов в макете ради пользователей. То есть исправлять неконтрастные цвета.
Процесс такой: сверстайте с цветами из макета, откройте в Chrome Dev Tools вкладку CSS Overview и запустите тест. Он покажет все используемые на странице цвета и уровни контрастности. Затем можно исправить цвет в палитре выбора и перенести в код.
А если дизайнер всё же вернётся и что-то скажет? Ну, это упущение дизайнера, его ответственность. А если заказчик скажет? Тут сложнее, но можно объяснять это как умышленную правку ради UX. Но обычно цвет не сильно меняется.
Есть другая проблема — текст на фоне изображений. Проблема в том, что фото или что-то сложное состоит из огромного количества цветов. Из-за многообразия экранов, невозможно предсказать поверх какой части будет находиться текст.
WCAG на этот счёт говорит, что нужно осуществить проверку контрастности с каждым цветом той части изображения, поверх которой находится текст. Это сложно и многие инструменты такое проверять не умеют.
Если у сайта ко всему прочему есть CMS, то одно изображение может быть заменено на другое и контент-менеджер проверять контрастность в сотне точек точно не будет. Лучше вообще избегать наложения текста поверх изображений.
Но если очень хочется, то простой совет — добавьте одноцветную подложку для текста. Вариант два: затемните место наложения текста через градиент. Вариант три: добавьте эффект «гало» тексту через тень. Но лучше всего подложка.
#a11y
Контрастность определяет соотношение между цветом текста и цветом фона, что влияет на читаемость, утомляемость глаз и способность визуального восприятия контента людьми с нарушениями зрения. Это самая частая проблема доступности по данным WebAIM.
Существует два алгоритма измерения контрастности: WCAG и APCA. Первый существует с момента появления стандарта WCAG и используется во всех текущих версиях стандарта, но даёт ложно-позитивные результаты для некоторых сочетаний цветов.
APCA более новый и надёжный алгоритм. Он учитывает восприятие человеческого глаза, поэтому более точно отражает контрастность. APCA заменит текущий алгоритм в стандарте WCAG 3, а пока массовым остаётся старый алгоритм WCAG.
Есть 3 критерия WCAG, которые затрагивают контрастность:
- 1.4.3 Contrast (Minimum);
- 1.4.6 Contrast (Enhanced);
- 1.4.11 Non-text Contrast.
Я сосредоточусь на 1.4.3. Потому что 1.4.6 выдвигает повышенные требования и исходит из того, что 1.4.3 удовлетворён. А 1.4.11 рассматривает нетекстовый контент, там иные требования и эта проблема не входит в топ самых распространённых.
Критерий 1.4.3 выдвигает следующие требования к уровню контрастности текста:
- 4.5:1 для текста размером до 24px или полужирного текста размером до 19px;
- 3:1 для текста размером от 24px или полужирного текста размером от 19px.
Проблема со стороны разработчиков, которые задают цвета в CSS, в том, что они получают от дизайнеров готовые макеты. Какие цветам там есть, такие переносятся в код. То есть контрастность текста — зона ответственности дизайнеров.
Поэтому исправление проблемы стоит начать с дизайна: установить требования и добавить в чеклист проверки. Инициатива может исходить и от разработки на этапе передачи макета в виде комментариев о недостаточной контрастности.
Для проверки контрастности текста в Figma есть плагины. Я пользуюсь плагином Contrast, но есть много других. Также рекомендую Polychrome, хоть он и работает по алгоритму APCA, он точнее отражает реальный уровень контрастности.
Если продукт большой, над ним работают несколько команд и есть дизайн-система, то проблему контрастности стоит решать на уровне дизайн-системы. Проверить палитру, гайды по использованию цветов, модули типографики.
А если это маленький проект, дизайнер сдал макет, получил оплату и ушёл? Частое явление в заказной разработке сайтов. Тут я предлагаю брать ситуацию в свои руки и отходить от цветов в макете ради пользователей. То есть исправлять неконтрастные цвета.
Процесс такой: сверстайте с цветами из макета, откройте в Chrome Dev Tools вкладку CSS Overview и запустите тест. Он покажет все используемые на странице цвета и уровни контрастности. Затем можно исправить цвет в палитре выбора и перенести в код.
А если дизайнер всё же вернётся и что-то скажет? Ну, это упущение дизайнера, его ответственность. А если заказчик скажет? Тут сложнее, но можно объяснять это как умышленную правку ради UX. Но обычно цвет не сильно меняется.
Есть другая проблема — текст на фоне изображений. Проблема в том, что фото или что-то сложное состоит из огромного количества цветов. Из-за многообразия экранов, невозможно предсказать поверх какой части будет находиться текст.
WCAG на этот счёт говорит, что нужно осуществить проверку контрастности с каждым цветом той части изображения, поверх которой находится текст. Это сложно и многие инструменты такое проверять не умеют.
Если у сайта ко всему прочему есть CMS, то одно изображение может быть заменено на другое и контент-менеджер проверять контрастность в сотне точек точно не будет. Лучше вообще избегать наложения текста поверх изображений.
Но если очень хочется, то простой совет — добавьте одноцветную подложку для текста. Вариант два: затемните место наложения текста через градиент. Вариант три: добавьте эффект «гало» тексту через тень. Но лучше всего подложка.
#a11y
👍7❤2🔥1🤔1🌚1