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

Комментарии (5)


  1. gwer
    09.02.2016 18:27
    -1

    Какой-то единой статьи где были разобраны все способы я не нашел, вся информация была разбросана по блогам и отдельным публикациям
    Есть такая штука, документацией зовется. Там внизу все способы расписаны.


    1. fetis26
      09.02.2016 18:33
      +1

      Там очень подробно рассказывается как конфигурировать библиотеку, но не говорится что стоит за каждым способом и уж тем более как будет выглядеть способ на практике и в чем его особенности.


      1. gwer
        09.02.2016 18:59
        -1

        Я же сказал, внизу. Там всё содержимое публикации кроме достоинств и недостатков.


        1. fetis26
          09.02.2016 19:15
          +2

          Я знаю про эти ссылки. Я их все прочитал. Но процитирую себя

          вся информация была разбросана по блогам и отдельным публикациям.