- PVSM.RU - https://www.pvsm.ru -

Способы генерации SVG-спрайтов на примере библиотеки svg-sprite

SVG sprites intro

Недавно я решал задачу организовать все 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 [1], внутри которого объявляется элементы для дальнейшего использования. Каждому элементу присваивается id, по которому этот элемент будет вызван в теге use [2].

Пример использования

<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 [3], который решает эту проблему.

Преимущества: Метод хорош тем, что предоставляет вам контроль над встраиваемой иконкой через CSS или атрибуты. Вы сможете легко менять ее размеры или цвет.

Недостатки: Скорее всего потребуется некий механизм (макрос, хелпер, функция), который будет генерировать код вставки иконки. При генерации приходится указывать атрибут viewBox и размеры. Согласно спецификации элементы внутри defs не должны отображаться, поэтому нельзя будет визуально оценить как выглядят спрайты после оптимизации. Впрочем, svg-sprite помогает в этом и может создать файл с образцами всех иконок.

В настоящее время использовать этот метод нет смысла, его улучшенной версией является Режим symbol.

Режим symbol

Принцип работы этого режима аналогичен предыдущему, но для задания элементов используется тег symbol [4]. Этот элемент, согласно спецификации, может содержать атрибут viewBox, поэтому отпадает необходимость указывать его при использовании заданного символа. Также элементы, созданные с использованием symbol, отображаются при рендере, что упрощает визуальный контроль созданных спрайтов. В остальном применение этого метода не отличается от Режима defs.

Пример использования

<svg width="50" height="50">
    <use xlink:href="#ei-archive"></use>
</svg>

Преимущества: Аналогично предыдущему режиму (легкая смена цвета и размеров).

Недостатки: Вам также понадобится вспомогательный механизм для вставки иконок. Однако, прочих недостатков метода defs этот режим лишен.

Режим view

В основе этого метода лежит возможность создания именованных областей просмотра для вашего документа в самом документе. Делается это с помощью тега view [5]. Созданный таким образом спрайт можно использовать двумя способами.

Как обычную фоновую картинку из первого режима

<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.

Автор: fetis26

Источник [6]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/html/111841

Ссылки в тексте:

[1] defs: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs

[2] use: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use

[3] svg4everybody: https://github.com/jonathantneal/svg4everybody

[4] symbol: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/symbol

[5] view: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/view

[6] Источник: https://habrahabr.ru/post/276463/