Доступные SVG
Масштабируемая векторная графика (SVG, Scalable Vector Graphic) все чаще становится предпочитаемым форматом графики в интернете сегодня. Возможно, вы тоже уже использовали SVG вместо иконочного шрифта или графики в форматах jpg, gif и png. Рассмотрим, как это влияет на пользователей вспомогательных технологий и что нужно, чтобы обеспечить благополучный пользовательский опыт для всех.
Графика и альтернативный текст
Перед тем как перейти к собственно доступным SVG, разберемся с несколькими основными вопросами о графике, доступности и альтернативном тексте.
1. Нуждается ли графика в альтернативном тексте?
Если графика выполняет чисто декоративную роль, альтернативный текст не нужен.
В тегах <img> должен быть атрибут alt для валидности, но его можно оставить пустым (без пробелов), разметка <img src=»pathtofile.svg» alt=»»> будет по прежнему валидной.
2. Какой контекст у графики и окружающего ее текста?
Если графика окружена текстом или содержимым, в котором есть альтернативный текст, то дополнительный альтернативный текст в атрибуте alt не нужен. Например:
Какой альтернативный текст наиболее оптимален для графики, которой необходим атрибут alt (см. пример 4 для подробной информации)? В зависимости от содержимого изображения, он может быть разным:
3. Есть ли у графики функция? Если так, то она должна быть донесена до пользователя.
Например, вместо точного описания того, что представлено на иконках…

Пример плохого кода:
…передайте пользователю контекст иконки.
Пример хорошего кода:
Для более полного понимания ознакомьтесь со статьей WebAIM “Alternative Text” и руководством W3C по доступности изображений.
Примеры в статье работают с браузерами, поддерживающими SVG (IE 10+, FF, Chrome и Safari) и наиболее распространенными скринридерами: Jaws, NVDA, VoiceOver (VO) и Narrator.
Способы подключения SVG на страницу
Для самой базовой имплементации SVG у нас есть следующие варианты:
1. SVG в img src
See the Pen SVG as img src by Heather Migliorisi (@hmig) on CodePen.
Перед тем, как продолжить, проверьте статистику браузеров посетителей вашего сайта. Если используется версия Safari Desktop 9.1.1 или iOS Version 9.3.2, а также более поздняя версия, то этого кода достаточно.
Однако многие пользователи по прежнему используют более старые версии Safari или IOS, поэтому нам надо добавить role=»img» , вот так: <img src=»linktofile.svg» alt=»Pixels, my super cute cat» role=»img»> .
И спасибо разработчикам, пофиксившим этот баг Safari/WebKit.
Этот пример хорош в качестве самого простого способа подключения SVG, но он не дает нам доступа к содержимому SVG с помощью AT (Assistive technology) или CSS/JS. Поэтому, если нам нужно больше контроля над SVG, мы инлайнируем его непосредственно в HTML.
2. Инлайновый SVG
Инлайновый SVG дает более полный контроль и более предсказуемые результаты, чем при использовании с <use> или <img> , так как исходники SVG непосредственно доступны в DOM, а DOM полностью открыт для API вспомогательных технологий.
Возьмем тот же базовый SVG из примера с <img> и попробуем добавить движение глаз. Мы можем сделать это с помощью JavaScript, если мы вложим SVG непосредственно в HTML.
See the Pen Basic SVG — Cat by Heather Migliorisi (@hmig) on CodePen.
Так как в SVG нет никакого видимого текста, описывающего графику, нам надо добавить альтернативный текст:
- внутри <svg> , добавив <title>A short title of the SVG</title> , который должен быть первым потомком родительского элемента — это будет использоваться как подсказка при наведении курсора.
- описание, при необходимости (оно не будет зачитываться).
В соответствии со спецификацией W3C, нам не надо делать ничего дополнительно, кроме добавления <title> и, возможно, <desc> так как они доступны Accessibility API. К сожалению, поддержка в браузерах пока недостаточна (см. Chrome и Firefox).
Чтобы гарантировать доступ AT к <title> и <desc> :
Добавьте соответствующий ID к <title> и <desc> :
- <title >Название SVG</title>
- <desc >Более длинное и полное описание сложной графики.</desc>
В теге <svg> добавьте:
- aria-labelledby=»uniqueTitleID uniqueDescID» используйте ID названия и описания; подключение и названия, и описания обеспечивает лучшую поддержку в скринридерах, чем aria-describedby .
Еще один момент:
- в теге <svg> добавьте role=»img» (таким образом, SVG не будет проходиться браузерами, которые добавляют SVG роль группы).
Итак, добавляем анимацию (моргание глаз):
Обновите название/описание так, чтобы оно точно описывало изображение:
3. Вложение SVG с помощью object или iframe
Сейчас я стараюсь держаться подальше от использования <object> или <iframe> . Они неадекватны в плане использования со скринридером.
Вот как это было у меня.
Итак, выбираем метод вложения SVG и добавляем tabindex=»0″ :
Используя нашего моргающего кота из последнего примера, нам надо заменить role=»img» на role=»group» .
И с этого момента все становится хуже.
Добавьте элемент в SVG <text> , в котором будет находится содержимое <title> и, возможно, <desc> (для NVDA):
Затем добавьте класс, чтобы спрятать текст визуально, оставив содержимое доступным для скринридеров. Мы можем сделать это, задав font-size: 0 .
Итак, мы пришли к тому, что <title> (а, по возможности, и <desc> ) и <text> содержат одинаковый контент, для поддержки JAWS и NVDA.
Примечания:
- <object> и <iframe> не работают в Chrome. Chrome видит содержимое запасного варианта ( img src ), поэтому вы можете скинуть весь текст туда, скопировав его в третий (или в четвертый) раз.
- JAWS не читает содержимое <text> (кроме отмеченного aria-labelledby / describedby )
Иконки
Есть несколько статей на тему замены иконочных шрифтов SVG. Мне было любопытно, облегчит ли использование SVG для иконок имплементацию их доступности. В смысле, могут ли браузеры поддерживать <title> , заданный в основном SVG, при использовании <use> . Увы, не могут. Но это можно сделать с самой иконкой и я сейчас покажу как.
После создания файла SVG, содержащего иконки (я люблю использовать для этого icomoon) и подключения его в документ, нам нужно определить паттерны, необходимые для сайта (иконка+ссылка, иконка+текст, просто иконка). Исходя из этих паттернов, мы можем разработать соответствующий метод применения альтернативного текста.
В начале код иконки обычно выглядит как вот этот из генератора иконок:
Пример №1: отдельная иконка со смыслом
Иконки со смысловой нагрузкой требуют альтернативного текста. Этот метод похож на инлайнирование SVG.
- обновите текст названия так, чтобы он отражал предназначение иконки, допустим, это сервисная поддержка мобильных устройств.
- добавьте role=»img» в <svg> (так как SVG не подключается последовательно, он не всегда распознается AT. Например, следующие варианты не работают Mac — VoiceOver + Chrome или Safari, Windows — NVDA + FF).
Еще раз, нам нужно смотреть статистику браузеров, чтобы узнать, надо ли нам сделать что-то еще. Если у пользователей сайта Chrome 49.1 или новее, мы можем на этом остановиться.
Однако, если у большинства пользователей более старые версии Chrome, то нам надо добавить id=»xxxx» к <title> и aria-labelledby=»xxxx» к <svg> .
Здесь стоит в очередной раз поблагодарить разработчиков Chrome за исправленный баг.
Пример №2: отдельная декоративная иконка
Декоративные иконки (то есть иконки, дублирующие информацию, переданную текстом или не имеющие особого значения) не нуждаются в альтернативном тексте, их надо прятать от скринридера. В следующем примере мы прячем SVG с помощью aria-hidden=»true» .
See the Pen yJYVpa by Heather Migliorisi (@hmig) on CodePen.
Пример №3: иконка-ссылка без текста
Для иконок-ссылок без текста, мы можем использовать aria-label в элементе <a> , чтобы добавить описательный альтернативный текст. В нашем случае к ссылке добавлен aria-label=»See Picked Pens» .
Пример №4: иконка-ссылка со статическим текстом
Для иконок-ссылок с текстом надо использовать aria-label в ссылке, добавляя альтернативный текст с описанием.
С aria-label в теге a скринридер не читает текст внутри ссылки, поэтому мы добавили aria-label=»See Picked Pens» в a .
Пример №5: иконка-ссылка с динамическим текстом
Итак, предположим в ссылке у нас динамическое значение текст + иконка. В таком случае мы не должны использовать aria-label в ссылке, так как значение динамического текста будет утрачено. В таком случае мы можем использовать тег span и текст, спрятанный за экраном. Числовым значением в id=»itemsInCart» тега span является динамически добавляемый элемент.
- добавьте дополнительный span с остальным альтернативным текстом (типа “предметов в вашей корзине”);
- добавьте этому span класс class=»offscreen-text» , чтобы визуально прятать его;
- добавьте aria-hidden=»true» в svg .
Все образцы иконок:
See the Pen Accessible SVG Icons by Heather Migliorisi (@hmig) on CodePen.
Сложные изображения: доступные графики
Замечательно, что мы можем использовать SVG вместо PNG и JPG, особенно при отображении сложного контента типа графиков. Было бы чрезмерным передавать всю информацию с графика в атрибуте alt , поэтому задание альтернативного текста в изображении будет непростым. Но, используя SVG, мы можем сделать весь текст доступным непосредственно.

1. Настройка файла
Порядок слоев — в Adobe Illustrator слои SVg экспортируются снизу вверх. Это важно, потому что мы хотим настроить слои так, чтобы они могли логично переключаться с клавиатуры в ходе чтения. Группа “Jaws” должна быть в коде сначала, поэтому в иллюстраторе слой “Jaws” находится в самом низу.

Именование слоев — это хорошая практика, тем более что названия слоев будут добавляться как id при экспорте SVG. Не волнуйтесь насчет одинаковых имен, в таком случае, к id будет добавляться число.

Группирование слоев — важно обратить внимание на то, как сгруппированы элементы. Текстовая метка + ключ элемента вместе со столбиком графика объединяются в одну группу для каждого варианта графика (Jaws, NVDA и т.д.). Это сделано для понимания прочитанного при использовании скринридеров. В некоторых браузерах пользователь может нажать на столбик и соответствующий текст будет зачитан и/или выделен.
Сохранение/экспорт — для гарантии я держу две версии своего SVG, одну для редактирования в Illustrator, а вторую для редактирования кода. Версию для работы в Illustrator я сохраняю через меню “сохранить как”, а более чистую версию для веба через “файл → экспорт → svg”.
Оптимизация — это последнее, что нужно сделать перед ручным редактированием SVG. Инструмент от Джейка Арчибальда SVGOMG отлично справляется с этим. Добавьте SVG, затем переключитесь в режим просмотра “CODE”, чтобы увидеть именно то, что переключает каждая функция. Не забудьте про опцию “prettify”, ведь мы еще будем редактировать код вручную и он должен быть читаемым.
Лучше всего воздержаться от ручного редактирования SVG (добавления доступности) до полной уверенности в его готовности. Потому как после начала ручного редактирования, работа с SVG в редакторе (Inkscape/Illustrator/и т.д.) может случайно изменить что-либо из добавленного вручную.
Контроль за исходниками — если вы используете контроль версий на основе git (git, SourceTree и т.д.), добавляйте SVG в коммит. Управление файлом в одной из систем версий поможет решить проблемы с неудачными изменениями в нем, особенно если он был открыт и сохранен в редакторе после ручного исправления, так как Illustrator не понимает любой код для доступности ( aria-* ) и удаляет его.
2. Добавление доступности к SVG
Проходимость для скринридеров — SVG делается проходимым во всех браузерах после добавления role=»group» в <svg> . В соответствии с новой спецификацией SVG, это должно указывать на роль графического документа. Однако, спецификация по прежнему находиться в режиме разработки и в браузерах еще не реализована.
Название и описание — так как у нас есть текстовые элементы в SVG, работающие как название и описание, мы привяжем их к элементу <svg> с помощью aria-labelledby=»graph-title» и aria-describedby=»graph-desc» .
Очистка разметки SVG — удалите все странности, создаваемые Illustrator. Например, к нашему элементу <text> добавлено несколько <tspan> . Скрин ридер может зачитать отдельные буквы вместо слова целиком (“J” “a” “w” “s” “- 44%” вместо “Jaws — 44%”). Поэтому надо удалить необязательные <tspan> , оборачивающие отдельные буквы.
Плохой пример:
Исправленный пример
Добавление ссылки на опрос — это разумное решение, так как график основан на результатах опроса. В SVG 2 это не обязательно, но пока мы добавим xlink: к href .
Больше об использовании xlink вы можете узнать из статьи Дадли Стори “We’ll Always Have Paris: Using SVG Namespacing and XLink”.
Добавление семантических ролей — к группам, содержащим столбцы графика, метку и ключ. Сделаем группу, содержащую список всех столбцов, так как большинство скринридеров зачитывают общее число и позицию каждого элемента списка:
Отдельные группы будут размещаться внутри этой группы-списка:
Добавление метки к списку — это даст пользователям вспомогательных технологий больше информации о графике, с которым они взаимодействуют. Метка добавляется к группе, содержащей список aria-label=»bar graph» .
Тестирование и исправление — тестировать надо скринридером. Как и ожидалось, скринридер считывает название, описание и ключи элементов списка. Но он также проходит через процентные значения на y-осях, каждом прямоугольнике и каждой линии.
Небольшое замечание по скрытию элементов (прямоугольников, кругов) от вспомогательных технологий в SVG. Единственный способ для этого — добавить им role=»presentation» . Таким образом вы отключаете нативную семантику для accessibility API. Если вам надо спрятать много элементов, то, к сожалению, вы не можете просто обернуть их тегом <g> и добавить role=»presentation» . Хорошая новость состоит в том, что новая спецификация SVG Accessibility решает большую часть этих проблем. Элементы, такие как формы без альтернативного текста, будут рассматриваться так, как если бы у них была роль none или presentation .
Скрытие форм/линий — все элементы с геометрическими формами прячутся путем добавления role=»presentation» .

Скрытие текстовых элементов — мешающие текстовые элементы надо спрятать от скринридера (на рисунке выше они подсвечены желтым цветом, это процентные значения у вертикальной оси, линия горизонтальной оси и столбцы в графике) путем добавления role=»presentation» и aria-hidden=»true» .
Демо-видео использования скринридеров:
Интерактивные изображения
Еще лучше, в сравнении с диаграммами и графиками, обстоят дела с доступностью интерактивных изображений. Рассмотрим простую хронологическую инфографику. Она разбивается на верхнюю часть с заголовком и раздел хронологии, который в свою очередь разбивается на сегменты, каждый из которых содержит заголовок, изображение и описание.

Добавим этой инфографике немного жизни и анимируем временные сегменты. Вместо того, чтобы показывать всю информацию сразу, мы выведем только время и круг с названием кошачьей активности. При взаимодействии пользователя с временем или названием будет выводиться остальная информация.
1. Настройка файла
Все то же самое, что и в секции настройка файла предыдущего раздела. Но после описания оптимизации для веба можете смело пропускать все об анимации CSS и переходить непосредственно к доступности.
2. Доступность
Стили удалены из следующих примеров для упрощения кода, но они, разумеется, есть в работающем демо.
Проходимость для скринридеров — чтобы SVG был проходимым во всех браузерах, добавьте к SVG role=»group» /
Название и описание — в нашем примере мы можем использовать текст в верхней части SVG ( <g > ) в качестве названия и ссылаясь на него с помощью aria-labelledby в <svg> .

Затем добавим id к <desc> и привяжем его к <svg> с помощью aria-describedby .
Добавление семантических ролей — добавьте семантические роли к группам, содержащим хронологию и ее отдельные сегменты. Вот группа с полным списком: <g role=»list»> .
Добавьте метку к списку: <g role=»list» aria-label=»the timeline, from morning to night»> .
Отдельные временные сегменты будут элементами списка: <g role=»listitem»> .
Взаимодействие/доступность с клавиатуры — сразу после каждого элемента <g> с role=»listitem» добавьте <a xlink:href></a> так, чтобы он охватывал все содержимое группы. На данный момент это единственный способ добавить интерактивность к SVG.
Добавьте туда же tabindex=»0″ , чтобы обеспечить фокусируемость во всех браузерах.
Исправление семантики ссылок — обратите внимание, что ссылки указывают сами на себя. Это не семантичные ссылки, так как они не ведут к чему-либо и могут смутить пользователей скринридеров. Поэтому добавим role=»img» , чтобы обозначить, что это изображение, а не ссылка.
Доступность текста внутри временных сегментов — добавление роли изображения прекращает проход элементов вспомогательными технологиями, поэтому нам надо добавить aria-labelledby с идентификаторами текстовых элементов в том порядке, в котором они читаются.
Добавление скрытого описания для изображений — используйте <tspan> с классом для скрытия элемента так, что визуально он скрыт, но остается в DOM.
Добавление идентификатора к атрибуту aria-labelledby в xlink так, чтобы он стал читаемым.
Добавление стилей для фокуса — настройка стилей для фокуса необходима пользователям, осуществляющим навигацию в браузере с помощью клавиатуры. Мне нравятся эти стили, поэтому я добавила их и для наведенного состояния.
Добавление JavaScript для фокуса окна — в SVG при навигации по ссылкам окно не всегда сдвигается так, чтобы элемент оказался в области видимости. Причина этого в том, что некоторые браузеры (баг-репорт добавлен и, надеюсь, скоро будет исправление) прокручивают элемент <svg> целиком, не учитывая, что некоторые дочерние элементы могут оказаться за экраном. Поэтому мы добавим немного JavaScript к прокрутке окна, чтобы обеспечить видимость сфокусированных элементов.
Есть и более эффективные способы, но для нашего быстрого примера хватит и этого:
See the Pen Accessible Interactive SVG by Heather Migliorisi (@hmig) on CodePen.
Видео с демонстрацией работы скринридеров:
SVG и режим повышенной контрастности
И еще одна проблема: Windows и режим повышенной контрастности для людей со слабым зрением, использующих эту возможность для улучшения читаемости содержимого. Это проблема потому, что при использовании этой возможности может измениться цвет текста или тела документа, но элементы в SVG не обновляются при изменении режима контрастности.

Хорошая новость: у нас есть специальные медиа-запросы для решения этой проблемы.
Вот пример исправлений для раздела с иконками в этой статье:
Заключение
Задавайте при необходимости альтернативный текст:
- Если альтернативного текста нет, прячьте SVG от вспомогательных технологий с помощью aria-hidden=»true» .
- Если альтернативный текст есть:
1. Добавьте название и/или описание в элемент SVG (или ссылку на них). 2. Используйте роли для добавления семантических значений (типа role=»list» , role=»listitem» ). 3. Прячьте графические и группирующие элементы, которые не следует зачитывать с помощью role=»presentation» . 4. Прячьте текстовые элементы, которые не следует зачитывать с помощью role=»presentation» и aria-hidden=»true» .
Для интерактивных SVG:
- Установите фокус с помощью xlink и tabindex=»0″ .
- Если ссылка не выполняет функции ссылки, добавьте соответствующую семантическую роль.
- Добавьте JavaScript для настройки фокуса окна.
- Задайте CSS для выделения focus: outline .
Тестируйте с разными скринридерами и браузерами. Тестируйте в различных режимах контрастности. Тестируйте навигацию с клавиатуры.
Благодарности
Огромное спасибо Амелии Беллами-Ройдс и Леони Уотсон за проверку примеров и выявление проблем. Я бы не смогла написать эту статью без их помощи.
Как изменить SVG иконку: атрибуты и CSS свойства
HTML, CSS
В предыдущих сериях…
Сегодня будем работать с inline кодом, посмотрим, какие бывают атрибуты у тега <svg> . Разберем случай, почему может не работать смена цвета иконки, прописанная в файле CSS.
Где взять inline код SVG-иконки
Если вы скачали готовую графику в формате .svg, то этот файл можно открыть в любом редакторе кода и увидеть тот самый inline код. Как мы помним, векторная графика описывает изображение с помощью специальных формул для создания фигур. При этом используются тег <svg> (контейнер для хранения SVG графики), внутри которого помещается один или несколько тегов <path> (для хранения координат прорисовки фигуры или части её). Этот код можно скопировать и вставить в html файл в том месте, где нужно расположить иконку.
Для примера возьмем иконку твиттера. Скопируем тег svg из файла иконки и вставим в HTML.
Содержимое svg кода
Итак, мы подключили иконку в формате svg inline, теперь рассмотрим код подробнее.
Так отобразится в браузере:
Пример inline кода

Мы видим тег <svg> и <path> , у которого есть атрибут d с координатами точек на плоскости, по которым рисуется фигура. В данном случае тег <path> один, изображение состоит из одной фигуры, но изображение может состоять из нескольких фигур — тогда будет несколько тегов <path> .
Атрибуты
Перейдем к атрибутам тега <svg>
xmlns=»http://www.w3.org/2000/svg» — данный атрибут прописывает путь к стандарту svg, в котором описана эта иконка
viewBox=»0 0 512 512″ — указывает на ту область иконки, которую мы видим в браузере
class=»twitter-icon» — как и другим элементам, можно задать класс и стилизовать по нему в CSS файле
Теперь добавим некоторые атрибуты самостоятельно.
width=»256″ height=»256″ — при помощи этих атрибутов можно настраивать размер иконки
Атрибуты fill , stroke , stroke-width в SVG
Эти атрибуты можно применить к тегу <svg> и тогда они распространятся на всю иконку. А можно применить к отдельному <path> — тогда они будут работать только в области, описанной в конкретном <path> . В нашем случае иконка состоит всего из одного <path> , поэтому без разницы, к чему применить данные атрибуты.
fill=»red» — заливка цветом
stroke=»green» — цвет обводки
stroke-width=»10″ — толщина обводки
Вот так мы переделали иконку при помощи атрибутов:
Пример inline кода с атрибутами

Интерактив по ховеру
При помощи CSS будем менять поведение иконки при наведении на нее курсором (по ховеру). Вернемся к изначальному коду без дополнительных атрибутов. Копируем класс иконки и стилизуем в файле CSS. Зададим свойство fill: blue; и далее по псевдоклассу :hover меняем на fill: rgb(145, 8, 199);
Результат в браузере:
Пример inline кода, стилизация в CSS
Внимание!
Этот прием будет работать только в том случае, если в html коде фигуры не прописан нигде атрибут fill=»» . Если вы работаете в CSS, то лучше убирать все атрибуты типа fill и stroke , чтобы не было путаницы. И переносить их в файл CSS в качестве свойств.
Заключение
Любой файл .svg можно открыть в редакторе кода. Сам код можно копировать и использовать в файле .html
Кастомизировать иконку можно при помощи атрибутов. Но создать интерактивность получится только при помощи стилизации в CSS файле. При этом важно следить за тем, чтобы контроль заливки или других свойств, которые будут меняться, происходил только в одном месте, в файле .css . В противном случае интерактив не заработает, так как значения атрибутов перебьют значения свойств.
Svg где брать
Explore, search and find the best fitting icons or vectors for your projects using wide variety vector library. Download free SVG Vectors for commercial use.
Easy To Search and Find
Using ML powered search, find the right vector you are looking for easier
Stying & Remixing
Make basic changes on an icon or vector witout needing a design software
Optimized Vectors
All served icons and vectors are optimized with our SVGO based compressor.
Community Powered
From me, to us. Share your work, help the community grow and get link attributions
Commercial Friendly
Most icons and vectors useable for your commercial projects without any royalties
Always Free, No Premium
We don’t show premium content while you are trying to find free assets.
Vector Collections
See our latest featured vector collections, choose the desired style of vector collections to list from the tabs. Browse 433 pages of icon collections by color and style.