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

Автор: @alexnozer
Download Telegram
Alt картинок:
1) Скриншот сайта smashing magazine в браузере Chrome на Android. Возле строки поиска расположена кнопка с иконкой телефона, на котором отображен текст. Кнопка включает режим чтения.

2) Скриншот сайта smashing magazine в браузере Chrome на Android в режиме чтения. Лишние элементы интерфейса скрыты, контент отображается в оттенках сепии, шрифтом без засечек, со 100% размером текста.

3) Скриншот сайта smashing magazine в браузере Chrome на Android в режиме чтения. Открыто меню настроек режима чтения. Доступные опции: Найти на странице, Внешний вид, Перевести...

4) Скриншот сайта smashing magazine в браузере Chrome на Android в режиме чтения. Открыто всплывающее окно настроек режима чтения. Вверху три кнопки выбор цветовой схемы: Светлая, Тёмная и Сепия (выбрана). Под кнопками выпадающий список для выбора типа шрифта, выбрана опция Без засечек. Под списком ползунок для изменения размера шрифта, установлен на 100%.
👍42
Забытый скроллбар

Последнее время я часто стал замечать на сайтах горизонтальный скроллбар буквально на десяток пикселей. Всё дело в разработчиках на MacOS. Сейчас объясню.

Дело в том, что поведение скроллбара на MacOS и Window отличается. На MacOS скроллбар отображается поверх страницы и не занимает места. А на Windows скроллбар при стандартных настройках занимает 17px.

В CSS есть замечательная единица vw — ширина текущего вьюпорта. Разработчики на MacOS используют эту единицу, чтобы растянуть блок на всю ширину экрана. И у них всё хорошо. А на Windows блок растянется на всю ширину и к нему прибавится ещё 17px для вертикального скроллбара. В итоге и появляется тот самый горизонтальный скроллбар, потому что блок превысил ширину вьюпорта на эти 17px.

Как быть? Тестировать проект не только на MacOS, но и в других системах при помощи Browserstack, LambdaTest, виртуальной машины или реальных устройств.

А для CSS есть лайфхак. Ширину скроллбара можно вычислить:

body {
--sb: calc(100vw - 100%);
}
Мы от ширины текущего вьюпорта (например, 1920px) отнимаем 100% ширины <body>, которая как раз включает всё, кроме скроллбара (1903px). Разница — и есть ширина скроллбара (17px). Чтобы это работало правильно, у <body> не должно быть горизонтальных margin и padding, и width должен быть стандартным, то есть 100%. Все эти условия соблюдаются в 99% случаев, поэтому этот хак можно использовать.

.full-width-block {
width: calc(100vw - var(--sb));
}
Это будет работать, потому что все элементы вложены в <body> и будут наследовать объявленное в нём кастомное свойство
--sb.

Другой лайфхак заключается в том, чтобы объявить свой настоящий vw, в котором будет учитываться скроллбар:

body {
  --sb: calc(100vw - 100%);
--vw: calc(100vw - var(--sb));
}

.full-width-block {
width: var(--vw);
}
На MacOS и мобильных устройствах, где скроллбар плавающий, его ширина будет равна 0, поэтому все эти формулы там тоже будут работать. Ссылка на демку codepen, которую можно открыть на разных устройствах и протестировать.
👍15❤‍🔥8🔥4
Дополнение к посту выше ⬆️

В MacOS есть настройка, которая переключает режим отображения скроллбара. Можно сделать так, чтобы он занимал место (16px), как в Windows. Делается это в настройках (Settings →Appearance). При этом подход, приведённый в предыдущем посте, тоже будет работать.
👍6
Подключение шрифтов с Google Fonts

Скорее всего, вы подключаете на сайт сторонние шрифты. Если сайт небольшой, то, скорее всего, вы найдёте шрифт на Google Fonts, скопируете сниппет и вставите его в <head>:

<head>
<!-- ... -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
</head>


Шрифт подключится, всё будет работать (при условии указания font-family). Но что на самом деле тут происходит и зачем нужны все эти теги? Тут стоит сделать отступление и разобраться, как работает сеть. Чтобы загрузить что-то с удалённого сервера, браузеру нужно:
1) найти URL
2) определить тип ресурса
3) разбить URL на составляющие (схема, домен, путь, параметры и т.д.)
4) определить IP-адрес сервера по имени домена (DNS Lookup)
5) "поздороваться" с сервером (TLS Handshake)
6) обменяться ключами безопасности (SSL)
7) запросить ресурс
8) подождать ответа от сервера
9) скачать ресурс
10) обработать ресурс

Вернёмся к сниппету.

<link rel="preconnect" href="https://fonts.googleapis.com"> 

Сообщает браузеру, что нужно заранее подключиться к домену fonts.googleapis.com. Выполняются этапы 1-6, чтобы при последующих обращениях к этому домену не делать лишнюю работу и не тратить время. На этом домене расположен сервер, который генерирует шрифты по указанным параметрам и CSS-файл с директивами @font-face, которые и подключают шрифт.

<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 

Делает то же самое, но уже к домену fonts.gstatic.com и в режиме CORS. Это домен CDN, на которых лежат сгенерированные файлы шрифтов.

<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">

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

Помимо всего прочего, каждый запрос к доменам Google сопровождается передачей информации об устройстве, браузере, настройках и т.д. С одной стороны, эти данные используются, чтобы сгенерировать оптимальный шрифт (для новых браузеров woff2, для старых woff, ttf, eot). С другой стороны, Google есть Google и их основной доход - продажа данных рекламодателям.

Итого имеем: два запроса на предварительное соединение, один запрос за CSS, запросы за шрифтами и передача данных. Вместо этого сделайте следующее:
1) скачайте CSS-файл с определением @font-face по ссылке, которую сгенерировал Google
2) скачайте нужные шрифты из этого файла
3) положите CSS-файл рядом с другими стилями или скопируйте код в ваш файл стилей
4) положите шрифты рядом с проектом
5) удалите все <link> от Google Fonts

Это улучшит время загрузки шрифтов и перформанс, уменьшит количество запросов, уберёт необходимость в предварительном подключении и не будет передавать данные в Google.
12👍5🔥2
Публичный черновик WAI-ARIA 1.3

На днях был опубликован первый публичный черновик спецификации WAI-ARIA 1.3. Эта спецификация описывает все aria-атрибуты и роли, которые можно использовать в HTML и SVG для того, чтобы сделать сайты и приложения более доступными для вспомогательных технологий. На текущий момент актуальная версия спецификации - WAI-ARIA 1.2, которая стала рекомендацией 6 июня 2023 года. WAI-ARIA 1.3 была доступна, но находилась в статусе редакторского черновика. Изменение статуса на публичный черновик означает, что документ в целом готов и теперь представлен публике для обсуждения и ревью. А это, в свою очередь, означает, что после нескольких итераций правок есть все шансы, что документ станет кандидатом в рекомендации, а затем рекомендацией.

Вообще круто, что скорость разработки спецификаций увеличилась. Например, в 2023 году произошло два важных события в мире доступности: рекомендацией стали стандарты WCAG 2.2 и WAI-ARIA-1.2. Если всё и дальше будет двигаться такими темпами, то в ближайшие год-два мы увидим WCAG 3 и WAI-ARIA-1.3 в качестве новых рекомендаций. А вместе с WAI-ARIA-1.3 могут обновятся и несколько вспомогательных, но очень полезных документов - ARIA Authoring Practices Guide (APG), Core Accessibility API Mappings и Accessible Name and Denoscription Computation.

Я планирую разобрать, что нового в WAI-ARIA-1.3 и опубликовать это тут.
🔥64👍1😍1
Interop 2024

Стартовал Interop 2024. о чём в своих блогах рассказали основные участники этой инициативы. Interop - это проект по улучшению кроссбраузерной совместимости. Начался он с инициативы Web Compat 2021. Основные браузеры (Chrome, Edge, Firefox и Safari) договорились и выбрали несколько направлений, по которым хотели достичь кроссбраузерной совместимости. Для каждого направления пишутся тесты (web platform tests) и браузеры соревнуются, кто больше тестов пройдёт. Дашборд с цифрами доступен всем желающим и обновляется в течении года, а в конце года подводятся результаты. Такой подход стимулирует разработчиков браузеров вкладываться в улучшение фич, чтобы не отставать от конкурентов. Нам же, как разработчикам, это хорошо, потому что достигается кроссбраузерная совместимость и появляются новые фичи.

После Web Compat 2021 эта инициатива продолжилась в следующем году под названием Interop 2022 и с тех пор стала ежегодной. В этом году браузеры выбрали довольно большой список направлений, по которым будут работать:
- Доступность
- Вложенность в CSS
- Custom Properties
- Declarative Shadow DOM
- font-size-adjust
- HTTPS URL для веб сокетов
- IndexedDB
- Layout
- События указателя и мыши
- Popover API
- Относительные цвета
- requestVideoFrameCallback
- Стилизация скроллбара
- @starting-style и transition-behavior
- Направления текста
- text-wrap: balance
- URL

К этому списку добавляются и те тесты, которые не удалось пройти в предыдущих Interop и Compat. Следить за ходом инициативы можно на странице Interop 2024.
🔥2
jQuery умер, да здравствует jQuery.

Говорят, что jQuery умер. Но на днях анонсировали jQuery 4.0.0 Beta. То есть он жив и активно развивается. В связи с этим событием моё мнение по поводу этой библиотеки и отношения к ней. Мнение может не совпадать с мнением большинства.

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

Прежде всего, jQuery - это библиотека. Сравнивать её с фреймворками не корректно. Да, React тоже библиотека, но в реальном мире к нему прикручивают много обвязки и используют как фреймворк. А фреймворки дают каркас приложения, подход к разработке, добавляют ограничения и снижают уровень проектных знаний. Хорошо про это рассказал Илья Климов в одном из видео на примере Vue. Фреймворки нужны для разработки приложений с большим количеством интеракции и бизнес-логикой на клиенте.

Но не все разработают такие приложения. Более того, таких приложений достаточно мало. По данным Web Almanac 2022, React используется на 8% сайтов, Vue на 3%, Angular на 2%, в то время как jQuery на 81%. Помимо больших проектов на фреймворках, есть огромное количество небольших сайтов и приложений, которые разрабатывают веб-студии, диджитал агентства, маленькие аутсорсинговые компании, фрилансеры и т.д. Большое количество проектов в интернете сделаны по классической модели с рендерингом разметки на сервере, и небольшим количеством JavaScript для интерактивности на клиенте.

Для таких проектов jQuery все ещё подходит. Он прост, легко осваивается новичками, упрощает работу с DOM, событиями и предлагает много сахара. Ещё одной крутой особенностью jQuery является экосистема. За десятилетия существования, сообщество создало огромное количество плагинов для решения самых разнообразных задач.

При этом jQuery - это всего лишь библиотека JavaScript. Никто не запрещает использовать современные фичи: модули, Promise, async/await, шаблонные литералы, классы, современные Web API и сторонние пакеты с npm. Да даже @vue/reactivity туда можно засунуть, если хочется реактивности. Код на jQuery можно писать красиво, структурировать, разделять на модули и раскладывать по папкам, но для этого нужен опыт. А если проект "сделал и забыл", как это бывает на фрилансе и в студиях, то и какая разница?

Есть две проблемы с jQuery: спагетти-код и размер бандла. Спагетти-код тянется со времен, когда фронтенда, как направления, не было, а сам JavaScript много чего не умел, не было никаких сборщиков и пакетных менеджеров. Никто не задумывался об архитектуре, просто брали и писали какую-то логику. Размер бандла же может стать проблемой, если стоит задача иметь хорошие метрики производительности. jQuery весит порядка 30кб min+gzip. Но такая ли это проблема в мире, где мы грузим столько же рантайма фреймворка и ещё пол мегабайта логики на нем? В 4й версии jQuery переписали на ESM, а значит можно будет делать tree shaking и code splitting.

Выводы. jQuery все ещё норм для небольших проектов, где надо быстро или "сделал и забыл". Его можно применить для прототипирования, проверки гипотез, MVP. На jQuery можно писать нормальный структурированный код и использовать современные фичи JavaScript. Не все проекты в мире пишутся на фреймворках, есть много популярных решений с jQuery под капотом, В определённых ситуациях он все ещё может быть неплохим выбором.
👍83🔥3🤔1🌚1🙈1
"Новый критерий WCAG"

Со мной поделились ссылкой на новый критерий WCAG 2.2. И я считаю, что он очень важен!

P.S. Эта страница выполнена в стиле спецификаций W3C, но является шуткой. Авторы предлагают новый "критерий", который в ироничном виде и с использованием ненормативной лексики призывает делать интерфейсы доступными.
😁7❤‍🔥4
Про меню

Что такое меню в пользовательских интерфейсах? Набор горизонтальных ссылок в шапке сайта — меню. Вертикальный набор ссылок, переключающих экраны в мобильном приложении — меню. Список действий над файлом в верхней части приложения (например, File -> Save As...) — меню. Раскрывающийся при нажатии на иконку-бургер список категорий товаров в магазине — меню.

В спецификации ARIA есть роли menu и menubar, а в спецификации WHATWG есть элемент <menu>. Есть большой соблазн использовать их не по назначению. Периодически я встречаю такое. Давайте разбираться.

Согласно спецификации, menu и menubar — это виджеты, которые предлагают список действий или функций, которые пользователь может вызвать. Эта роль уместна для меню, которые похожи на меню в десктопных приложениях. Что особенного в меню десктопных приложений? Дело в том, что в таких приложениях нет понятия "страница" и "URL-адрес". Пункты меню в десктопных приложениях выполняют какие-то действия, но не меняют URL.

Вспомните любое десктопное приложение, например Photoshop, Figma, VSCode, Word, Paint. У всех них в верхней части есть горизонтальное меню — это menubar. При нажатии пункта в этих меню происходит действие — открытие выпадающего вертикального меню — это и есть menu. Разница между menubar и menu в значении aria-orientation по умолчанию: horizontal для menubar и vertical для menu. Пользователи ожидают от menu и menubar возможности навигации между пунктами при помощи клавиш со стрелками, Home и End. От menu ожидается навигация стрелками вверх/вниз, а от menubar — влево/вправо.

Согласно той же спецификации, внутри menu и menubar могут располагаться только элементы с ролями menuitem, menuitemcheckbox и menuitemradio. Также элементы можно группировать при помощи роли group и разделять при помощи separator (в ARIA 1.3).

А вот типичный блок с ссылками на сайте не является меню в контексте спецификации. Об этом пишут и в ARIA практиках. Набор ссылок на сайте — это навигация. Поэтому паттерн меню в таком случае не применим. Навигация — это про страницы, URL-адреса и фрагменты (якори). Меню — это про вызов действий в приложении. Это очень похоже на вопрос "кнопка или ссылка".

Так вот: если при нажатии на элемент происходит переход на другую страницу (или перерисовка с изменением URL в SPA), переход к разделу на странице (якорь), страницу можно открыть в новой вкладке, новом окне, в инкогнито, ссылку можно скопировать, сохранить в закладки, поделиться, ссылка должна индексироваться — это навигация. Для этого нужно использовать элементы с ролями navigation и link, то есть встроенные элементы <nav> и <a>. Можно добавить список, если элементов больше 3-4.

<nav aria-label="Main">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/products">Products</a></li>
<li><a href="/pricing">Pricing</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>


Если при нажатии на пункт открывается вложенное меню, диалоговое окно, меняется часть интерфейса приложения, происходит какое-то действие с данными, меняются настройки, режим работы и т.д. — это меню. Для этого нужно использовать паттерны menu и menubar. Так как встроенных в HTML аналогов нет, то меню можно сконструировать из семантически-нейтральных элементов и соответствующих ролей. Часто его делают из списка. В этом есть смысл, но я предпочитаю использовать кнопки с ролями, так как они сами по себе интерактивные, в отличие от элементов списка.

<div role="menu">
<button type="button" role="menuitem">Save...</button>
<button type="button" role="menuitem">Save As...</button>
<button type="button" role="menuitemcheckbox" aria-checked="false">Autosave</button>
<button type="button" role="menuitem">Open</button>
<button type="button" role="menuitem">Undo</button>
<button type="button" role="menuitem">Rendo</button>
</div>


Контекстные меню, открываемые щелчком правой кнопкой мыши по элементу или при помощи сочетания Shift+F10 на Windows — это тоже меню. Но не используйте роли menu и menubar для навигации на сайте.
🔥13👏21👍1
Alt картинки:
Пример классического меню в WebStorm. В примере есть горизонтальный menubar, выпадающие menu, разные типы пунктов меню (menuitem, menuitemcheckbox, menu button) и separator.
🔥4
Роли-контейнеры: toolbar.

В предыдущем посте я рассказал о ролях menu и menubar. Напомню: это роли-контейнеры для элементов menuitem, menuitemradio и menuitemcheckbox. По функционалу это набор каких-то действий и функций, которые может вызвать пользователь. Но это не набор навигационных ссылок. Предполагается горизонтальная (для menubar) и вертикальная (для menu) стрелочная навигация.

Есть и другие роли-контейнеры для интерактивных элементов, например toolbar.

toolbar — контейнер для интерактивных элементов, таких как кнопки, чекбоксы, переключатели и т.д. toolbar предназначен для группировки набора интерактивных элементов, которые визуально сгруппированы и для уменьшения количества шагов табуляции.

В качестве примеров: панель инструментов в текстовом или графическом редакторе.

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

Есть некоторые интерактивные элементы, которые используют стрелки в своих нуждах. Например, <input type="number">. При попадании фокуса стрелки вверх/вниз увеличивают/уменьшают значение, а стрелки влево/вправо перемещают каретку. Такие элементы не рекомендуется использовать внутри toolbar, чтобы избежать конфликтов со стрелками и не сломать навигацию. Но такие элементы можно использовать в конце toolbar, если их избежать не получается.

Для toolbar подразумевается aria-orientation="horizontal", то есть элементы расположены горизонтально и есть стрелочная навигации между элементами. Это можно переопределить, указав атрибут с другим значением. Если на странице более одного toolbar, то всем им нужно добавить имя при помощи aria-label или aria-labelledby. Использовать toolbar стоит только когда элементов 3 и более.

Скринридеры озвучивают роль и имя (если оно есть), а также выход за пределы toolbar:

<div role="toolbar" aria-label="Text settings">
<button type="button" aria-label="Bold"></button>
<button type="button" aria-label="Italic"></button>
<button type="button" aria-label="Underline"></button>
</div>
При последовательной навигации это будет зачитано так:

Text settings toolbar
Bold button
Italic button
Underline button
Out of toolbar


Кейсы использования:
- панель инструментов в редакторе чего-либо
- группировка связанных по смыслу интерактивных элементов в приложениях с большим количеством таких элементов.

Описание паттерна toolbar.
Пример реализации toolbar в текстовом редакторе. Обратите внимание на то, что внутри toolbar различные элементы и паттерны.
Спецификация роли toolbar.
9👍3🔥3
CSS isn't magic

Мой коллега по цеху, Стас (кому-то может быть знаком по статьям на хабре), завёл канал CSS isn't magic. В нём он стремится показать, что CSS не является магией и рассказать о способах решения старых задач при помощи новых возможностей. Если вам интересен CSS, то рекомендую подписаться.
👍21
Прозрачность в hex

Формат hex при указании цветов в CSS, пожалуй, является самым популярным. Формат с нами давно, к нему все привыкли, он идёт по умолчанию практически во всех редакторах, есть куча инструментов для трансформации, он самый короткий (короче только некоторые именованные цвета). Если не стоит задача делать динамические палитры в браузере, поддерживать мониторы с широким охватом цветов, использовать математику для расчёта цветов, то hex — это самый очевидный выбор.

Но бывало же такое, что дизайнер в макете везде использовал hex, но в одном месте захотел сделать прозрачность? В итоге все цвета задаются в hex, а цвет с прозрачностью приходится писать в rgba. В этот момент разрушается единообразие формата указания цветов. Появляются как минимум две разные нотации, а rgba ещё и кучей разных способов можно записать, но об этом в другой раз.

Так вот, уже достаточно давно в hex можно указывать прозрачность, но почему-то я ещё ни разу не видел, чтобы этим кто-то пользовался. Возможно, потому что это не удобно: представьте себе 60% прозрачности в шестнадцатеричном формате? Это будет 99, а не 3C, как можно было подумать 🤯

В hex альфа-канал задаётся добавлением в конец шестнадцатеричных чисел. То есть формат записи следующий: #RRGGBBAA или #RGBA.

То есть:

#000, #000F, #000000 и #000000FF — чёрный непрозрачный, то же самое, что rgb(0 0 0) и rgb(0 0 0 / 1)

#0000 и #00000000 — чёрный прозрачный, то же самое, что rgb(0 0 0 / 0)

#000C и #000000CC — чёрный с 80% прозрачности, то же самое, что rgb(0 0 0 / 0.8)

#00000040 — чёрный с 25% прозрачности, тоже самое, что rgb(0 0 0 / 0.25)
👍5🔥1
Семантика заголовка с подзаголовками

Kevin Powell, известный по ютуб-каналу про CSS, задал в твиттере вопрос: как семантически разметить заголовок как на фото? Есть верхний текст, основной заголовок и нижний текст. Весь этот текст объединён в один смысловой блок. Так как же это лучше сверстать?

Так как текст связан, тут хорошо подойдёт роль group. Также вспоминаем первое правило ARIA: не использовать ARIA. Поэтому подбираем элемент с ролью group, который есть в HTML. И такой существует как раз для нашей задачи — <hgroup>:

<hgroup>
<p>Plant parenting simplified</p>
<h1>From wilted to wow: Plant care made easy</h1>
<p>Tired of drooping leaves? Learn how to revive your plants and create a thriving indoor oasis.</p>
</hgroup>

<hgroup> в спецификации HTML.
👍54👏1
Alt картинки:

Скриншот блока на сайте. Он состоит из текста "Plant parenting simplified" перед заголовком, текстом "From wilted to wow: Plant care made easy" самого заголовка, текста "Tired of drooping leaves? Learn how to revive your plants and create a thriving indoor oasis" после заголовка и кнопки-ссылки "Get Started".
🤨1
Роли-контейнеры: group

Продолжаю рассказывать про роли-контейнеры. На очереди group. Эта роль предназначена для группировки объектов пользовательского интерфейса, которые не должны попадать в список содержимого. Давайте разбираться.

Что за объекты пользовательского интерфейса? Это любые элементы, будь то интерактивные или неинтерактивные. Это отличает group, например, от рассмотреных ранее menu, menubar и toolbar, которые предназначены для интерактивных элементов.

Группируемые при помощи group элементы не попадают в список содержимого. Речь о функции в скринридерах, которая позволяет открыть окно со списком всех ссылок, кнопок, списков, заголовков и ориентиров. Это отличает group от region, который попадает в список ориентиров, если для него задано имя.

group не подразумевает никакую клавиатурную навигацию, а служит только для группировки частей интерфейса. Добавить клавиатурную навигацию можно, однако об этом нужно предупредить пользователей, которые не ожидают от group такого поведения. Для group также нужно задавать имя при помощи aria-label или aria-labelledby.

Группировать при помощи group можно не только произвольный набор элементов на странице, но и элементы внутри некоторых виджетов. Так, внутри menu и menubar можно группировать menuitem, menuitemcheckbox и menuitemradio. В combobox и listbox можно группировать option. А в tree можно группировать treeitem.

В HTML есть встроенные элементы с ролью group. Элемент <fieldset> представляет group. Если внутри есть <legend>, то его текст будет использован как имя для <fieldset>. Элементы <hgroup>, <address>, <details> и <optgroup> также представляют group в дереве доступности, поэтому вручную задавать роль group им не рекомендуется.

Где применять на практике? В первую очередь стоит использовать встроенные элементы HTML вместо ARIA-ролей. Если встроенные элементы не подходят, тогда можно указать роль group на семантически нейтральных элементах <div> или <span>:

<div role="group" aria-label="Галерея">
  <img src="img1.jpg" alt="Описание...">
  <img src="img2.jpg" alt="Описание...">
  <img src="img3.jpg" alt="Описание...">
</div>


Варианты использования:
- группировка связанных полей (<fieldset> + <legend>)
- группировка контактных данных (<address>)
- группировка заголовка и подзаголовка (<hgroup> + <h*> + <p>)
- группировка второстепеного, менее актуального или скрываемого контента (<details> + <summary>)
- группировка опций (<select> или <datalist> + <optgroup> + <option>)
- группировка menuitem, menuitemradio и menuitemcheckbox в menu и menubar
- группировка option в listbox и combobox
- группировка treeitem в tree
- группировка любых других связанных элементов интерфейса (<div> или <span> + role="group")

Спецификация роли group.
🔥81🤩1
The WebAIM Million

Вышели результаты ежегодного исследования от WebAIM. В этом исследовании анализируется миллион домашних страниц сайтов на предмет наличия различных ошибок доступности.

Анализ проводится при помощи инструмента WAVE, а по объёмам это самое большое исследование доступности сайтов. Поэтому можно сказать, что оно в каком-то виде отражает состояние доступности сайтов по интернету.

С результатами можно ознакомиться в отчёте на сайте WebAIM. Интересной особенностью является возможность вбить домен вашего сайта и выяснить, попал ли он в выборку для исследования.
🔥2👍1
Gulp 5.0

Как-то раз я делал пост про Gulp, в котором рассказывал, что он давно не обновлялся, многие зависимости и плагины устарели и предлагал варианты для замены. Но на днях, спустя почти 5 лет, у gulp произошёл релиз версии 5.0.

Так как это мажорная версия, то не обошлось без breaking changes. Отказались от поддержки Node <10.13, унифицировали механизм работы с glob, удалили старые флаги, уменьшили количество зависимостей и обновили оставшиеся, изменили библиотеку для работы со стримами и кучу всего другого.

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

В общем gulp жив, внезапно. Другой вопрос к экосистеме плагинов, за которую команда gulp не отвечает. Многие плагины тоже стоило бы обновить. Также вопрос в актуальности: функционал gulp практически полностью замещается parcel или CLI-инструментами, не говоря уже о сборщиках вроде Vite.
👍9
Статья про семантику

На Доке вышла статья про семантическую вёрстку в HTML. Это одна из моих любимых тем. Также это одна из спорных и не очевидных тем. Я, конечно же, не могу пройти мимо. На мой взгляд статья содержит ряд неточностей. Дам свои комментарии по этим моментам.

Семантическая вёрстка — особый подход к написанию HTML-разметки страниц. При этом подходе разработчик опирается не на содержание сайта, а на смысловое предназначение каждого блока и логическую структуру страницы.


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

<aside> — тег для дополнительного контента, используется для создания «сайдбара» или бокового меню на сайтах.


Один из самых распространённых стереотипов, наряду с картинкой о разметке классической страницы. <aside> — это не боковая колонка! <aside> — это второстепенный контент, который связан с окружающим контентом. Кажется мне стоит сделать отдельный, более подробный пост про этот элемент.

<nav> — контейнер для навигации со ссылками на другие страницы и разделы сайта


В спецификации есть примечание, что в <nav> не стоит заворачивать любую навигацию, а только основную. Если на странице несколько <nav>, то каждому из них нужно задавать имя.

Теги вроде <header> и <footer> — ориентиры.


Это верно только в том случае, когда они относятся к основному разделу страницы <body>. То есть между <body> и этими элементами нет других секционных элементов (<section>, <article>, <aside>, <nav>).

Уровень доступности сайта сам по себе — один из факторов ранжирования в поисковых системах.


Доступность не является фактором ранжирования. В официальных источниках от Google и Yandex такой информации нет. Core Web Vitals оказывает небольшое влияние. Оценка доступности хоть и отображается в Lighthouse, но это информационный показатель, он не входит в Core Web Vitals.

Семантическая вёрстка помогают и самим поисковым движкам. Они не понимают сам текст, его контекст и то, насколько он важен.


Роботы понимают текст и контекст, причём в первую очередь. Иначе куча сайтов с вёрсткой на <div>-ах бы не оказалась в топах поисковой выдачи. Качество текста, его смысл, связь с другим текстом на странице — один из решающих показателей при ранжировании. Об этом достаточно много упоминается в документации Google Search.

Семантические теги дают поисковым системам нужный контекст, помогают понять содержимое сайта и проиндексировать его относительно других со схожей тематикой.


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

Например, в Google под название сайта попадают заголовки второго уровня, если используете тег <h2>.


Семантические элементы действительно влияют на построение сниппетов, но больше влияния на это оказывает микроразметка.

Если тянет добавить к <div> классы вроде header, sidebar, content, post и footer, лучше использовать теги <header>, <aside>, <main>, <article> и <footer>.


Этот совет работает не всегда. sidebar не всегда <aside>, content не всегда <main>, post не всегда <article>. Иногда лучше написать <div> с одним из этих классов, чем использовать созвучный с классом элемент.
👍137
Фронтенд-фантазии

Наткнулся в твиттере на пост, что в следующей версии Bun можно будет писать комментарии в файле package.json и Bun не будет выдавать ошибок. На самом деле возможность хорошая, иной раз хочется добавить комментарий к npm-скрипту или пакету. Но, всё-таки, это формат json, со своей спецификацией и правилами, комментарии там запрещены синтаксисом. Bun мог бы реализовать поддержку существующих форматов json5 или jsonc, где комментарии разрешены.

Также недавно Рич Харрис, автор Svelte, был крайне удивлён: оказывается, конструкция <div /> не является валидной в HTML и не является сокращением для <div></div>. При этом в Svelte такая конструкция работает и было принято решение это исправить и привести парсер в соответствие со стандартом. А ещё подобная конструкция есть в JSX, наряду с бесполезными слешами в конце тегов.

Это всё натолкнуло меня на одну мысль: во фронтенде очень много придуманного "синтаксического сахара", который не является стандартизированным и валидным для того языка, в котором используется. И этот синтаксис придуман и внедрен авторами инструментов. В итоге получается забавная ситуация: мы вроде бы пишем код на HTML, CSS и JS, но в то же время пишем какой-то придуманный синтаксис, используем надмножества языков.

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

Я придерживаюсь мнения, что нужно всегда оставаться как можно ближе к веб-платформе. Иными словами я за стандарты. Возможно, это мнение не популярно, хотя есть немало сторонников этой идеи, некоторые даже пишут статьи по этой теме. У меня назрела идея тоже написать статью с разбором и примерами на эту тему.
👍7
<divelopers>
Нативные поповеры! В Chrome 114, который вышел в конце мая 2023, завезли Popover API. Firefox и Safari поддержали этот API и должны выкатить в ближайшее время. И это крутая новость! <button popovertarget="note"> Подробнее </button> <div id="note" popover>…
Шнурки

Последнее время на многих проектах я использую библиотеку UI-компонентов shoelace.style. Поэтому хочу поделиться опытом.

Библиотека построена на базе веб-стандартов и под капотом использует Lit. Каждый UI-компонент поставляется в виде веб-компонента. Это делает библиотеку независимой от фреймворков, что отличает её от таких решений, как MUI, Vuetify, Angular Material и т.д. При этом компоненты Shoelace можно использовать во Vue и Angular. С 19 версии React их полноценно можно будет использовать и там, а пока автор предоставляет для React компоненты-обёртки.

Другой особенностью Shoelace является устройство стилей. Библиотека предоставляет базовую светлую и тёмную темы. Это CSS-файлы, в которых содержатся токены в виде пользовательских свойств CSS (палитра, отступы, размеры, закругления, тени и т.д.) и несколько служебных классов. В остальном там нет никаких других стилей.

Все необходимые стили содержатся в Shadow DOM у каждого UI-компонента. Эти стили изолированы от внешнего воздействия, но по правилам Shadow DOM они наследуют значения наследуемых свойств и видят внешние пользовательские свойства CSS. Если подключена тема, то компоненты будут использовать объявленные в ней свойства. Если тема не подключена, компоненты будут работать, но потеряют свой внешний вид.

Можно создать свою тему, подключив CSS-файл со своими значениями пользовательских свойств. Такой вариант подойдёт, когда библиотека используются в качестве UI kit, то есть интерфейс приложения будет полностью построен на компонентах этой библиотеки.

Но можно использовать компоненты точечно. Если в проекте нужна только карусель и диалоговое окно, библиотека позволяет взять только эти компоненты и не тянуть лишнее. Самый простой способ — воспользоваться автозагрузчиком. Он ищет на странице компоненты и сам подгружает нужные для их работы модули. Можно подключить нужный компонент самостоятельно через <noscript>, как в старые добрые времена, или импортировать модуль в JS при помощи import или import().

Библиотека также поставляет API к каждому компоненту в виде атрибутов, свойств, методов, событий, пользовательских свойств CSS, слотов и частей (CSS Shadow Parts). Благодаря этому компоненты можно стилизовать практически как угодно. Это большой плюс, потому что некоторые библиотеки крайне сложно кастомизировать.

В основном над Shoelace работает один человек — Cory LaViska. Он активно развивает библиотеку и выпускает новые версии. Одни раз я столкнулся с багом и создал issue на github, которое было решено в течении нескольких дней. Также автор уделяет большое внимание доступности. При разработке компонентов он опирается на рекомендации WCAG и ARIA практики. В общем рекомендую взглянуть на эту библиотеку.
👍7🔥5🐳1