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

Для простой графики MDN рекомендует задавать role="img" и метку внешнему элементу SVG, чтобы вспомогательные технологии воспринимали его как одно изображение. Здесь используется практический шаблон: для каждого вхождения создаётся обёртка со ссылкой на собственную метку. Роль ARIA img

Где задавать доступную метку каждого экземпляра?

Задавайте имя элементу, представляющему конкретное вхождение. Если несколько отдельных графических элементов используют один символ, задайте каждому внешнему svg собственную ссылку aria-labelledby или aria-label. В общем символе оставьте только повторно используемую геометрию.

Так соблюдается различие между определением и его отображаемыми экземплярами. Элемент SVG use ссылается на графику и отображает повторно используемое содержимое через теневое дерево; созданные таким образом фигуры не являются обычными дочерними узлами DOM страницы. Поэтому повторное использование рисунка не создаёт в HTML отдельные редактируемые копии его внутренней метки. Структура документа — SVG 2

Заголовок, сохранённый внутри общего символа, также не может задавать разный текст для разных вхождений без дополнительного механизма именования. Например, один и тот же нейтральный рисунок плитки в одном месте может обозначать Образец «Альфа», а в другом — Образец «Бета». Эти имена относятся к двум вхождениям, хотя их геометрия одинакова.

Выбирайте способ именования в зависимости от того, где уже есть полезный текст:

Ситуация Рекомендуемый шаблон
Краткая видимая подпись называет графику Укажите её уникальный ID в aria-labelledby внешнего SVG.
Графике нужно имя, но видимой подписи нет Поместите уникальный title во внешний SVG и укажите на него через aria-labelledby либо используйте aria-label.
Графика лишь украшает текст, который уже передаёт всю информацию Скройте SVG от вспомогательных технологий, чтобы не добавлять избыточное имя.
Несколько вхождений должны оставаться доступными по отдельности Не объединяйте их в одно внешнее изображение role="img".

MDN рекомендует ссылаться на видимый текст, если он может служить именем SVG. В документации роли изображения также поясняется, что role="img" представляет содержимое как единую сущность, поэтому граница обёртки имеет значение. Элемент доступного имени SVG, Роль ARIA img

Создайте целую страницу с двумя отдельно именованными экземплярами

В следующем примере приведён полный HTML-документ, содержащий только искусственный текст и простой рисунок из круга и квадрата. JavaScript, внешний спрайт, библиотека или процесс сборки не нужны. На Mac сохраните его из текстового редактора кода в файл symbol-labels.html, затем откройте файл в настольном браузере.

Оба вхождения ссылаются на tile-mark, но внешние элементы SVG ссылаются на разные видимые подписи. Здесь применяется описанный MDN шаблон именования по видимому тексту. Атрибут href — актуальный механизм ссылок в SVG; MDN указывает, что xlink:href устарел. Элемент доступного имени SVG, Элемент SVG use

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Independently labeled SVG instances</title>
  <style>
    body {
      margin: 2rem;
      font-family: system-ui, sans-serif;
      color: #222;
    }
    .sprite {
      position: absolute;
      width: 0;
      height: 0;
      overflow: hidden;
    }
    .samples {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 1rem;
      max-width: 36rem;
      padding: 0;
      list-style: none;
    }
    .sample {
      padding: 1rem;
      border: 1px solid #777;
    }
    .sample svg {
      display: block;
      width: 5rem;
      height: 5rem;
      margin-bottom: 0.75rem;
    }
    @media (max-width: 30rem) {
      .samples { grid-template-columns: 1fr; }
    }
  </style>
</head>
<body>
  <svg class="sprite" xmlns="http://www.w3.org/2000/svg"
       aria-hidden="true">
    <defs>
      <symbol id="tile-mark" viewBox="0 0 48 48">
        <rect x="4" y="4" width="40" height="40" rx="6"
              fill="none" stroke="currentColor" stroke-width="2" />
        <circle cx="24" cy="24" r="9" fill="currentColor" />
      </symbol>
    </defs>
  </svg>

  <h1>Sample tiles</h1>
  <ul class="samples">
    <li class="sample">
      <svg xmlns="http://www.w3.org/2000/svg"
           viewBox="0 0 48 48" role="img"
           aria-labelledby="sample-alpha-label">
        <use href="#tile-mark" width="48" height="48"
             aria-hidden="true" />
      </svg>
      <span id="sample-alpha-label">Sample Alpha</span>
    </li>
    <li class="sample">
      <svg xmlns="http://www.w3.org/2000/svg"
           viewBox="0 0 48 48" role="img"
           aria-labelledby="sample-beta-label">
        <use href="#tile-mark" width="48" height="48"
             aria-hidden="true" />
      </svg>
      <span id="sample-beta-label">Sample Beta</span>
    </li>
  </ul>
</body>
</html>

Ожидаемые доступные имена — Образец «Альфа» и Образец «Бета». Это ожидаемые результаты, исходящие из разметки, а не результаты браузерного тестирования. Рисунок внутри каждой обёртки явно скрыт от вспомогательных технологий; именованный внешний элемент SVG остаётся доступным. В схемах доступности SVG различаются скрытые дочерние элементы и их доступный родитель. Сопоставления SVG с API доступности

Добавляя третье вхождение, повторно используйте href="#tile-mark", создайте новый ID подписи и обновите aria-labelledby этого вхождения, чтобы он указывал на неё. Оставьте ссылку на символ общей, а ссылку на метку — индивидуальной для каждого вхождения.

Экранный диктор также может отдельно озвучить видимые подписи. Если плитка не добавляет информации к подписи, используйте шаблон для декоративной графики: удалите role="img" и aria-labelledby из внешнего SVG, а затем задайте ему aria-hidden="true". Видимую подпись оставьте. В схемах SVG описано исключение через aria-hidden. Сопоставления SVG с API доступности

Какой механизм браузера отвечает за каждую часть компоновки?

В этом примере выполняются три отдельные задачи: расположение карточек, рисование символа и вычисление доступных имён. Изменение одного параметра автоматически не выполняет остальные задачи.

CSS Grid размещает элементы списка HTML. Объявление display: grid превращает непосредственные дочерние элементы контейнера в элементы сетки; grid-template-columns задаёт столбцы. Здесь медиазапрос переключает список с двух столбцов на один. Это меняет расположение карточек на странице. Основные понятия компоновки сетки

Координаты SVG управляют фигурами внутри каждой графики. Параметр viewBox="0 0 48 48" символа задаёт его координатный прямоугольник, а размеры элемента use определяют область просмотра для подключённого символа. Эти размеры не создают столбцы HTML-карточек и не задают интервалы между подписями. В SVG 2 явно различаются компоновка повторно используемой графики и компоновка CSS-блоков. Структура документа — SVG 2

Доступное именование связывает каждый внешний элемент SVG с текстом через aria-labelledby. Оно не рисует текст, не размещает подпись и не меняет размер графики. В рекомендациях W3C по именованию этот атрибут описан как ссылка на содержимое, используемое для вычисления доступного имени. Создание доступных имён и описаний

Это разделение даёт полезное правило для диагностики: проверяйте Grid, если карточки расположены неправильно, координаты SVG — если смещены рисунки, а ссылки для именования — если указаны неверные метки. Добавление x или y к use смещает повторно используемую графику в пространстве SVG, но не перемещает подпись HTML. Кроме того, размеры use не служат универсальной заменой масштабированию произвольных подключённых фигур: MDN описывает их действие при ссылке на SVG или символ с viewBox. Элемент SVG use

Что делать, если видимой подписи нет?

Используйте заголовок для каждого экземпляра, если графике нужно имя, но в дизайне нет подходящего видимого текста. Ниже приведён заменяющий фрагмент для первого видимого SVG в полном примере. Он по-прежнему использует существующий символ tile-mark:

<svg xmlns="http://www.w3.org/2000/svg"
     viewBox="0 0 48 48" role="img"
     aria-labelledby="sample-alpha-title">
  <title id="sample-alpha-title">Sample Alpha</title>
  <use href="#tile-mark" width="48" height="48"
       aria-hidden="true" />
</svg>

Для каждого дополнительного вхождения задавайте заголовку другой ID и обновляйте ссылку родительского элемента. MDN описывает title как элемент доступного именования SVG и рекомендует размещать его первым для совместимости с SVG 1.1. Текст заголовка не отображается непосредственно в составе рисунка, хотя браузеры обычно показывают его как всплывающую подсказку. Элемент доступного имени SVG

Если нужно короткое имя без элемента заголовка, замените aria-labelledby на aria-label="Sample Alpha" во внешнем SVG этого вхождения. Не оставляйте конфликтующие атрибуты именования: W3C указывает, что aria-labelledby имеет приоритет над aria-label. Поэтому оставшаяся ссылка может помешать новой строке стать именем. Создание доступных имён и описаний

Не пытайтесь задавать отдельный заголовок для вхождения, редактируя созданную копию. В SVG 2 указано, что теневое дерево экземпляра доступно только для чтения. В текущем рабочем черновике «Сопоставления SVG с API доступности» также ограничено сопоставление ссылок ARIA на ID с теневыми деревьями use. Это документированные ограничения; они не доказывают, что все браузеры ведут себя одинаково. Если оставить метку в авторской обёртке, не придётся полагаться на поиск в копии. Структура документа — SVG 2, Сопоставления SVG с API доступности

Как проверить и устранить неполадки?

Отдельно проверьте видимый результат и доступные имена в браузере на Mac. Изучите каждый внешний SVG в средствах доступности браузера, затем проверьте его с помощью VoiceOver. W3C специально рекомендует проверять вспомогательными технологиями имена, вычисленные с помощью aria-labelledby. Создание доступных имён и описаний

Используйте эти ожидаемые результаты как краткий список проверки:

  1. Оба рисунка отображаются со своими видимыми подписями.
  2. У каждого внешнего SVG есть роль изображения и соответствующее имя.
  3. Определение символа не отображается как дополнительная содержательная графика.
  4. При сужении окна меняется расположение карточек, а у каждой графики сохраняется метка.
  5. Изменение только второй подписи меняет только вычисленное имя второй графики.

Если обе графики получают одно имя, сначала сравните значения aria-labelledby. Затем убедитесь, что каждый указанный ID идентифицирует нужный текст. Не предполагайте, что связь устанавливается визуальной близостью: атрибут явно ссылается на элемент по ID. Создание доступных имён и описаний

Если весь рисунок объявляется одним изображением, хотя вам нужно несколько независимых изображений, проверьте, где расположен role="img". Одна роль изображения вокруг всей коллекции указывает вспомогательным технологиям воспринимать её как одну сущность. Для отдельных простых графических элементов используйте отдельные обёртки изображений. Роль ARIA img

Если вы действительно встраиваете файл SVG через HTML-элемент img, задавайте для каждого вхождения атрибут alt этого элемента. WHATWG определяет alt как эквивалентное резервное содержимое изображения. Для встроенного SVG используются другие механизмы именования, и он не поддерживает alt в качестве атрибута альтернативного текста. Стандарт HTML: элемент img, Введение в SVG в HTML

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

Источники