Stack — спрайт здорового человека

Stack — спрайт здорового человека

firefoxic

К сожалению почти везде рассказывают только про символьный спрайт. В действительности видов спрайтов есть минимум… пять! И Артур Трифонов собрал тестовую страничку для сравнения возможностей всех пяти видов во всех четырёх возможных вариантах использования:

Как видно из теста, символьный спрайт довольно ограничен в области применения — только и исключительно через use. Остальные не сильно от него оторвались. А вариант css-спрайта вообще, что-то странное вытворяет. И только stack показывает идеальный результат — во всех четырёх способах использования видим ожидаемые иконки.

Почему же рассказывают про символьный? В виду его большей распространённости, которая случилась, потому что раньше нужно было поддерживать IE, который не умел в спрайты, но был полифил svg4everybody, который для IE генерировал png-иконки вместо svg. Этот полифил работал только с символьным спрайтом. И на самом деле, в те времена использование svg для иконок хотя бы через use вместо иконочного шрифта — это уже было верхом профессионализма.

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

Статью Simurai аж от 2 апреля 2012 года можно считать первоисточником (во всяком случае все упоминания стека в вебе, включая недавнюю статью Вадима Макеева, ссылаются на неё). В ней довольно сложно описывается устройство. Но можно значительно проще.

Устройство стека

Отдельные SVG иконки внутри общего (корневого) SVG просто складываются друг над другом — отсюда и название stack. При этом в отличие от символьного спрайта, тег svg на symbol не меняется. Но добавляется встроенный стиль, которым все иконки полностью скрываются, и показывается только нужная при обращении к ней по ссылке на фрагмент.

Допустим есть пара квадратных иконок с горизонтальной линией в одной и вертикальной в другой.

horizontal-line.svg:

<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
 <path d="m 0 12 h 24" stroke="black" />
</svg>

vertical-line.svg:

<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
 <path d="m 12 0 v 24" stroke="black" />
</svg>

Берём их код и просто складываем вместе в одном файле друг за другом (в любом порядке), при этом заносим имена файлов в id соответствующих svg. Оборачиваем их все в общий svg, перенеся на него декларации неймспейсов (xmlns). А внутрь, перед всеми иконками добавляем простой стиль.

<svg xmlns="http://www.w3.org/2000/svg">

 <style> :root svg:not(:target) { display: none } </style>

 <svg id="horizontal-line" viewBox="0 0 20 20">
  <path d="m 0 12 h 24" stroke="black" />
 </svg>

 <svg id="vertical-line" viewBox="0 0 24 24">
  <path d="m 12 0 v 24" stroke="black" />
 </svg>

</svg>

Теперь мы можем использовать эти иконки из стилей в фоне псевдоэлементов, если они статичные. А если нужно их динамически перекрашивать, то вместо background мы можем использовать mask (лучше сокращённое свойство, если будут использоваться кастомные свойства), который скроет часть псевдоэлемента, не попадающую в форму иконки (принцип трафарета, но наоборот), а оставшееся мы можем легко перекрашивать через изменение background.

Если убрать тег <style>, то при обращении к любому фрагменту будут видны вообще все иконки, которые попадут во viewBox, указанный у запрашиваемого фрагмента (в случае данного примера будет виден плюсик, вместо одной из линий).

Автоматизация сборки стека

Для Gulp есть минимум три плагина для сборки спрайтов.

Огромный и тяжёлый монстр gulp-svg-sprite умеет собирать все пять видов спрайта. Но учитывая покрытие стеком всех юзкейсов, получается что бо́льшая часть функциональности этого плагина просто не нужна. К тому же он ещё и зачем-то в корневой svg добавляет viewBox с максимальными значениями из значений у иконок. Это не нужно, да ещё и мешает при стилизации — если этот viewBox получился не квадратным, то настроить видимый размер иконки на странице становится сложно.

В большинстве случаев используется gulp-svgstore. Он небольшой и лёгкий. Но у него есть несколько проблем, важнейшая из которых — он собирает только символьный спрайт.

А вот gulp-stacksvg нам подходит — собирает удобный стек и избавлен от известных болячек двух других. Да ещё и заменяет атрибуты width и height у иконок на viewBox с соответствующими размерами, если вдруг при оптимизации иконки забыли включить опцию предпочтения viewBox.

Демонстрация рендеринга фрагментов стека, собранного этим плагином, во всех юзкейсах, включая перекраску через маски.

По умолчанию он собирает иконки в файл stack.svg, но можно опцией output передать ему нужное имя файла (как с расширением, так и без него), например sprite, чтобы получить sprite.svg.

Report Page