Недавно я решал задачу организовать все SVG-файлы, используемые в проекте, в виде одного спрайта. До этого мне приходилось использовать самописное решение для такой задачи. На этот раз я решил воспользоваться популярной библиотекой svg-sprite, однако был сильно удивлен сколько разных способов создания она предлагает. Какой-то единой статьи где были разобраны все способы я не нашел, вся информация была разбросана по блогам и отдельным публикациям. Поэтому я решил собрать доступные в библиотеке способы для генерации спрайтов в одном месте, попутно проанализировав их преимущества и недостатки. Итак, поехали.
Режим CSS
Данный режим очень похож на привычный всем способ генерации спрайтов из картинок. Все файлы склеиваются в один, полученный файл ставится в качестве фона блока, а нужная иконка выбирается за счет смещения этого фона.
Пример использования будет выглядеть так
<i class="svg-ei-archive">ei-archive</i>
и соответствующий CSS-код
.svg-ei-archive {
background: url("svg/sprite.css.svg") 12.5% 0 no-repeat;
width: 50px;
height: 50px;
}
Приятно особенностью
svg-sprite
является возможность задать в каком виде вы хотите получить стили — в виде чистого CSS или под препроцессоры LESS, SASS, Stylus. Немного поигравшись с шаблонами вывода, можно настроить вывод иконок в виде миксинов и генерировать код только тогда, когда он действительно нужен.Преимущества: метод просто и понятен каждому, кто до этого работал со спрайтами.
Недостатки: невозможно указывать произвольные размеры, управлять цветом иконки. Не получится использовать в теге
img
Режим defs
Этот режим использует тег defs, внутри которого объявляется элементы для дальнейшего использования. Каждому элементу присваивается id, по которому этот элемент будет вызван в теге use.
Пример использования
<svg viewBox="0 0 50 50" width="50" height="50">
<use xlink:href="#ei-archive"></use>
</svg>
Для того чтобы
use
из примера смог отрендерить элемент, SVG с defs
должен быть также включен в тело документа. Стандартом допускается использовать внешний файлов в xlink:href
, однако это не поддерживается всеми версиями Internet Explorer. К счастью, существует полифил svg4everybody, который решает эту проблему.Преимущества: Метод хорош тем, что предоставляет вам контроль над встраиваемой иконкой через CSS или атрибуты. Вы сможете легко менять ее размеры или цвет.
Недостатки: Скорее всего потребуется некий механизм (макрос, хелпер, функция), который будет генерировать код вставки иконки. При генерации приходится указывать атрибут
viewBox
и размеры. Согласно спецификации элементы внутри defs
не должны отображаться, поэтому нельзя будет визуально оценить как выглядят спрайты после оптимизации. Впрочем, svg-sprite
помогает в этом и может создать файл с образцами всех иконок.В настоящее время использовать этот метод нет смысла, его улучшенной версией является Режим symbol.
Режим symbol
Принцип работы этого режима аналогичен предыдущему, но для задания элементов используется тег symbol. Этот элемент, согласно спецификации, может содержать атрибут
viewBox
, поэтому отпадает необходимость указывать его при использовании заданного символа. Также элементы, созданные с использованием symbol
, отображаются при рендере, что упрощает визуальный контроль созданных спрайтов. В остальном применение этого метода не отличается от Режима defs.Пример использования
<svg width="50" height="50">
<use xlink:href="#ei-archive"></use>
</svg>
Преимущества: Аналогично предыдущему режиму (легкая смена цвета и размеров).
Недостатки: Вам также понадобится вспомогательный механизм для вставки иконок. Однако, прочих недостатков метода defs этот режим лишен.
Режим view
В основе этого метода лежит возможность создания именованных областей просмотра для вашего документа в самом документе. Делается это с помощью тега view. Созданный таким образом спрайт можно использовать двумя способами.
Как обычную фоновую картинку из первого режима
<i class="svg-ei-archive">ei-archive</i>
и как отдельное изображение, встраиваемое с помощью идентификаторов фрагмента (fragment identifiers)
<img src="sprites.svg#ei-archive" width="50" height="50>
На мой взгляд очень удобно. Одна и та же иконка может быть и картинкой, и фоном в зависимости от ситуации. В настоящее время поддержка идентификаторов фрагмента полностью отсутствует в iOS 9.x, несмотря на то, что частичная поддержка была в предыдущей версии.
Преимущества: Можно использовать иконку как для фона, так и для изображения. Легко менять размер, если используется как изображение.
Недостатки: Проблемы с поддержкой в iOS в настоящий момент. Нельзя установить в качестве фона на блок произвольного размера. Нет возможности смены цвета через CSS.
Режим stack
Данный способ также использует именованные области просмотра, однако располагает их одну под другой, подобно слоям в Фотошопе. Каждая область скрыта по умолчанию и становится видна, при ссылке на нее через fragment idetifier
:root>svg {display:none}
:root>svg:target {display:block}
Соответственно, нам также доступны два способа использования.
Как фоновая картинка
.svg-ei-archive {
background: url(sprites.svg#el-archive) no-repeat 50% 50%;
}
и как обычное изображение
<img src="sprites.svg#ei-archive" width="50" height="50>
Ситуация с поддержкой браузерами тут немного хуже, чем в предыдущем способе. Помимо отсутствия поддержки в iOS 9, идентификаторы фрагмента не работают для фоновых изображения в Chrome по 48 версию включительно. Однако в будущем, когда ситуация с поддержкой улучшится, этот способ может стать очень популярным, потому что позволяет использовать одну и ту же иконку как для фона, так и для изображения без ограничений.
Преимущества: Аналогично предыдущему способу, но нет ограничений для изменения размера в зависимости от способа использования.
Недостатки: Проблемы с поддержкой браузерами в настоящий момент. Нет возможности смены цвета через CSS. Из-за особенностей метода все иконки скрыты по умолчанию, поэтому визуально оценить готовый спрайт затруднительно.
Бонус-режим inline-css
Этот метод не является стандартным способом для библиотеки svg-sprite, но может быть создан на ее основе. Смысл его заключается во встраивании самой иконки в файл-стилей через data-url. Библиотека svg-sprite предоставляет широкие возможности для кастомизации шаблонов вывода и дает доступ к исходному коду самой иконки. Поэтому есть возможность создать свой шаблон, который будет генерировать следующий код.
.el-archive {
background: url("data:image/svg+xml;[icon-data]");
}
Однако, на практике, решить эту задачу с наскока не удалось и вопрос требует более детального рассмотрения.
В качестве заключения
Представленные способы не являются единственными для создания SVG-спрайтов. Мне попадались и другие, более экзотические варианты. Какой способ лучше решаться придется вам исходя из того, какой набор иконок имеется и какие возможности для кастомизации вам нужны. На мой взгляд вполне production-ready можно считать режимы css и symbol.
gwer
fetis26
Там очень подробно рассказывается как конфигурировать библиотеку, но не говорится что стоит за каждым способом и уж тем более как будет выглядеть способ на практике и в чем его особенности.
gwer
Я же сказал, внизу. Там всё содержимое публикации кроме достоинств и недостатков.
fetis26
Я знаю про эти ссылки. Я их все прочитал. Но процитирую себя