Системы иконок и доступность
Что это такое
Система иконок — это стратегия доставки и подписи для набора иконок: как браузер их получает, как задаются их размер и цвет и что слышит скринридер, когда иконка появляется. Доставку выбирают обычно из трёх вариантов — файл-спрайт, на который ссылаются через <use>, встроенная в разметку графика или отрисовка через <img>; подпись же решает, декоративная иконка или информативная.
Почему это важно
От выбора доставки зависит, что вообще возможно. Иконка в <img> не наследует цвет, спрайт наследует, но анимировать его поэлементно нельзя, а встроенная разметка умеет и то и другое — ценой повторения путей. Пригоден ли интерфейс, решает выбор подписи: кнопка только с иконкой, без имени, объявляется как «кнопка», а декоративная иконка без aria-hidden вставляет бессмысленное содержимое в порядок чтения. Оба решения принимают один раз, а потом копируют сотни раз — поэтому система себя и оправдывает.
Ключевые идеи
Три модели доставки, три компромисса
Спрайт — один файл со всеми символами, и ссылаются на них через <use href="#name">. Файл кэшируется один раз, а иконки внутри можно перекрашивать через currentColor. Встроенная разметка даёт полный контроль над каждым элементом — анимацию, несколько цветов, части, которыми управляет сценарий, — но повторяет данные пути. <img> проще всего поставить и труднее всего приспособить: цвет не наследуется, внутренности не стилизуются.
<svg aria-hidden="true" focusable="false">
<use href="/icons.svg#search" />
</svg>
На практике разделяют так: спрайт — для множества иконок, которым нужны только цвет и размер, а встроенная разметка — для немногих, которые анимируются или используют несколько цветов.
Решите — декор или информация — и скажите об этом
Декоративную иконку скрывают от дерева доступности через aria-hidden="true" и focusable="false", а смысл несёт текст рядом. Информативной иконке дают имя: либо role="img" с aria-label, либо элемент <title> первым потомком.
<!-- Кнопка только с иконкой: имя несёт сама кнопка -->
<button type="button" aria-label="Поиск">
<svg aria-hidden="true" focusable="false">…</svg>
</button>
Не оставляйте это на волю случая: неподписанная декоративная иконка — шум, а неподписанная информативная — пропущенное слово.
Имя дают элементу управления, а не иконке
Когда иконка стоит внутри кнопки или ссылки, доступное имя принадлежит элементу управления. Добавьте aria-label и кнопке, и SVG — и имя обычно получится дважды, а скринридер объявит его с запинкой.
Размер в em, цвет через currentColor
Иконке, которая следует размеру и цвету шрифта вокруг, не нужна стилизация для каждого экземпляра, и она ведёт себя правильно, когда пользователь увеличивает базовый размер шрифта. Иконки в фиксированных пикселях эту настройку игнорируют и нарушают требование масштабирования.
.icon { inline-size: 1em; block-size: 1em; color: currentColor; }
Держите единый визуальный канон набора
Одна толщина обводки, одно соглашение о радиусе углов, одна внутренняя сетка (часто 24 на 24) и один оптический размер. Если иконки в этом расходятся, они выглядят так, будто пришли из разных продуктов, даже когда каждая нарисована хорошо; исправляется такое решением дизайна, а не изменением кода.
Практика
Проверьте подписи на одной панели инструментов
Возьмите панель кнопок только с иконками и проверьте доступное имя каждой в инспекторе доступности браузера. Исправьте каждый элемент управления, который объявляется без имени, и каждую декоративную иконку, которая появляется в дереве.
Готово, когда: у каждого элемента управления ровно одно ясное имя, и ни одна декоративная иконка не объявляется.
Сравните спрайт и встроенную разметку на одной иконке
Отрисуйте одну и ту же иконку дважды: из спрайта и встроенной в страницу. Поменяйте ей цвет, анимируйте и измените базовый размер шрифта.
Готово, когда: вы можете сказать, какой подход возьмёте для статичных иконок и какой для анимированной, с обоснованием.
Частые ошибки
- Декоративная иконка оставлена без подписи — порядок чтения заполняется бессмысленным содержимым; исправить: добавьте
aria-hidden="true"иfocusable="false". - Информативная иконка оставлена без имени — элемент управления объявляется без имени; исправить: поставьте подпись на элемент управления или
<title>на иконку. - Подписаны и кнопка, и её иконка — имя объявляется дважды; исправить: давайте имя только интерактивному элементу.
- Размер иконок в фиксированных пикселях — они игнорируют настройку размера шрифта у читателя; исправить: задавайте размер в
em, чтобы они следовали за текстом. - Шрифт иконок для новой работы — когда нужного глифа нет, шрифт молча ломается, а стилизовать глифы поэлементно нельзя; исправить: используйте SVG.
Что читать дальше
- Основы SVG (02-frontend/17-svg-icon-systems/01-svg-fundamentals) — система координат и правила стилизации, на которые опираются эти иконки.
- Доступность (WCAG / a11y) (02-frontend/11-accessibility-wcag-a11y) — доступные имена полностью разобраны там.
- Инструменты разработчика в браузере (02-frontend/27-browser-devtools) — именно в инспекторе доступности вы проверяете, что объявляется.