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

Пример 1 — Две неподписанные иконки с противоположными проблемами

Кнопка на панели несёт иконку-лупу, а в области статуса иконка предупреждения стоит рядом с сообщением. Одна из них объявляется слишком скупо, другая не сообщает ничего осмысленного. Скажите, что скринридер сообщает в каждом случае, и исправьте обе.

<button type="button" class="icon-button">
  <svg viewBox="0 0 24 24"><path d="M10 10l4 4" stroke="currentColor" /></svg>
</button>

<span class="status">
  <svg viewBox="0 0 24 24"><path d="M12 8v5" stroke="currentColor" /></svg>
  Платёж отклонён
</span>

Решение

<button type="button" class="icon-button" aria-label="Поиск">
  <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
    <path d="M10 10l4 4" stroke="currentColor" />
  </svg>
</button>

<span class="status">
  <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
    <path d="M12 8v5" stroke="currentColor" />
  </svg>
  Платёж отклонён
</span>

Кнопка объявлялась как «кнопка» без имени: у элемента управления, где есть только иконка, нет текстового содержимого, откуда взять имя. Как только подпись появляется на элементе управления, он объявляется как «кнопка, Поиск». Иконка статуса — обратный случай. Это декор рядом с текстом, который уже несёт смысл, поэтому видимость для дерева доступности вставляет в порядок чтения бессмысленное содержимое: получается «графика», а затем сообщение. Скрытие через aria-hidden и focusable убирает её из дерева полностью. Какое исправление применить, решает правило: дайте имя элементу управления, когда иконка — единственная подпись, и скройте иконку, когда рядом есть настоящий текст. Никогда не подписывайте оба, иначе имя объявляется дважды.

Пример 2 — Шрифт иконок, который ломается молча

Проект рисует свои иконки из шрифта, и если глифа в шрифте нет, на месте иконки остаётся пустой прямоугольник, причём ошибки не видно нигде. Скажите, чего стоит эта модель доставки, затем перейдите к набору символов SVG.

.icon { font-family: "Icons"; font-size: 24px; }
.icon-search::before { content: "\e902"; }

Решение

<svg class="icon" aria-hidden="true" focusable="false">
  <use href="/icons.svg#search" />
</svg>
.icon { inline-size: 1em; block-size: 1em; color: currentColor; }

Шрифт иконок кодирует каждый глиф как символ из области частного использования. Поэтому и глиф, которого в шрифте нет, и неверно заданная кодовая позиция, и заблокированный файл шрифта дают один и тот же молчаливый пустой прямоугольник, а чтобы показать одну иконку, шрифт приходится скачивать целиком. Спрайт, на который ссылаются через <use>, — один кэшированный файл символов: их можно перекрашивать через currentColor и задавать им размер в em, а если символа нет, это видимая ошибка, а не пустой прямоугольник. Тот же компромисс действует и внутри SVG: спрайт подходит множеству иконок, которым нужны только цвет и размер, а встроенная разметка — верный ответ для немногих, которые должны анимироваться или рисоваться в нескольких цветах.