Системы иконок и доступность

Что это такое

Система иконок — это стратегия доставки и подписи для набора иконок: как браузер их получает, как задаются их размер и цвет и что слышит скринридер, когда иконка появляется. Доставку выбирают обычно из трёх вариантов — файл-спрайт, на который ссылаются через <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.

Что читать дальше