Svg спрайт не работает отдельным файлом

Обновлено: 07.07.2024

При верстке макета из PSD часто иконки вставлены в формате SVG, а если нет — просим их у дизайнера. Ранее мы использовали иконочные шрифты, но недавно увидели преимущества спрайтов и решили попробовать с ними поиграться внедрить их в процесс разработки. Нам нравятся иконочные шрифты, но они имеют ряд недостатков(на эту тему почитайте CSSTricks). Эксперимент удался, и вот как мы организовали систему.

Условия

Что нам нужно от спрайтов:

  1. Гибкое управление размером, цветом и поведением(hover, focus etc) иконки
  2. Автоматизация, минимум ручной работы
  3. Подгрузка на страницу только необходимых иконок
  4. Удобная вставка иконок в разметку страницы (для шаблонизации html я использую jade)

Подробнее о том как работает наша сборка - можете почитать в репозитории. Для создания спрайта используем gulp, а именно:

  • gulp-svg-sprite - создание спрайта
  • gulp-svgmin - минификация SVG
  • gulp-cheerio - удаление лишних атрибутов из svg
  • gulp-replace - фиксинг некоторых багов, об этом ниже

Поехали

Устанавливаем плагины(мы это делаем глобально и потом линкуем):

В gulpfile объявляем плагины:

Готовим спрайт

Создаем svg-файл с тегами symbol.

Давайте разберемся, что тут происходит по частям.

Говорим откуда нам нужно взять иконки и минифицируем их. Переменная assetsDir - для удобства.

Удаляем атрибуты style, fill и stroke из иконок, для того чтобы они не перебивали стили, заданные через css.

Однако у данного плагина один баг - иногда он преобразовывает символ ‘>’ в кодировку '>' .
Эту проблему решает следующий кусок таска:

Теперь сделаем из получившегося спрайт и положим в папку:

dest:’../../../sass/_sprite.scss’ - здесь мы объявили, куда нужно генерировать стили для спрайта.

template: assetsDir + “sass/templates/_sprite_template.scss” - код шаблона, на основе которого будут генерироваться стили для спрайта.

sprite.svg - это наш спрайт. Внутри он будет содержать следующее(для простоты приведена пара иконок):

Код шаблона для генерирования стилей представлен на гитхабе.

Получаем _sprite.scss следующего содержания:

Скомпилированный css будет таким:

Обратите внимание, что размеры иконок выражены через em, что позволит нам в дальнейшем управлять ими через font-size.
Составляем итоговый таск, и запускаем его:

Подключаем на страницу

Итак мы получили svg-файл с иконками и scss-файл с оформлением. Иконки вставляем через миксин jade, т.к. это быстро и удобно:

Теперь, чтобы встроить иконку вызываем миксин с её именем:

Открываем страницу в браузере:


Пока размеры иконки в натуральную величину и имеют стандартный цвет. Изменим это(не в сгенерированном файле, а в главном):


Результат:

Кроссбраузерность

Мы подключаем иконку ссылаясь на внешний svg-файл, к сожалению не все браузеры поддерживают такой запрос. Для решения этой проблемы есть библиотека svg4everybody. Подключаем её и инициализируем:

Вот и все, мы получили рабочую систему подключения иконок через спрайты, но есть еще один момент.

Некорректные иконки

К сожалению, не все дизайнеры делают иконки по пиксельной сетке. В этом случае иконки будут “размываться”. Если вы экспортируете иконки из иллюстратора вам нужно включить пиксельную сетку и подогнать размер и расположение иконки под пиксельную сетку. Если вы работаете в готовыми svg-файлами - воспользуйтесь сервисом iconmoon для их правильного выравнивания. Также важно конвертировать stroke для иконок, о том как это сделать написано в документации iconmoon.

Если вы из тех разработчиков, кто только задумывается о внедрении в свой проект svg-спрайтов или из тех, кто давно хотел, но не знает с чего начать, эта статья определенно будет вам полезна. Об удобстве и пользе спрайтов вообще и SVG-спрайтов в частности немало информации как на родном, так и на иностранном языке. Поэтому, в этой статье, мы не будем останавливаться на вопросах целесообразности их использования, а перейдем непосредственно к сути.

SVG-спрайты бывают разные. Самый простой вариант – это склеивание всех иконок в один файл и последующее использование его в виде фоновой картинки со смещением background-position для каждой иконки. Все, кто работал ранее с растровыми спрайтами, знакомы с такой технологией и найдут ее для себя простой и понятной. К сожалению, в таком варианте спрайта масштабирование и управление цветом будет недоступно, также, как и возможность использовать спрайт в теге img.

Другие виды svg-спрайтов выглядят интереснее. Об их разновидностях, преимуществах и недостатках хорошо изложено в этой статье на Хабре. Там же рассказывается о библиотеке svg-sprite, к которой мы позднее вернемся.

Сегодня, мы рассмотрим генерацию и использование спрайтов, на примере символьного SVG-спрайта. Выбор в его пользу был сделан не случайно, это именно тот вариант спрайта, который имеет на сегодняшний день наилучшую поддержку браузерами, а также позволяет свободно управлять размером и цветом иконки.

Устройство спрайта

Символьный svg-спрайт, представляет собой один корневой элемент svg, внутри которого создаются области symbol , внутри которых содержится код svg-иконки. Каждому элементу symbol назначается уникальный id , по которому к нему в дальнейшем можно будет обратиться в документе.

Symbol создает шаблон из любых svg-объектов, который в дальнейшем можно многократно использовать с помощью тэга use . Контент, расположенный внутри symbol , не отображается на странице.
Предположим, у нас имеются две разные svg-иконки:

Для того, чтобы объединить их в спрайт, достаточно код каждой из них обернуть в элемент symbol , к нему добавить атрибут viewbox и указать уникальный id . Вот так выглядит самый простой символьный svg-спрайт.

Использование на странице

Чтобы иметь возможность использовать иконки из символьного svg-спрайта, в первую очередь, нужно добавить этот спрайт на страницу. Берем спрайт, полученный нами в предыдущем разделе, и вставляем на страницу.

После того, как спрайт находится на странице, вывести нужную иконку можно с помощью тэга use :

Управление с помощью CSS

Перед тем, как переходить к стилизации иконок средствами CSS, нужно удалить из спрайта атрибуты fill , stroke , style . Эти атрибуты в svg имеют больший приоритет и переписать их средствами CSS не получится. В нашем примере это атрибут fill . После его удаления, иконки станут черными:

Если вы не хотите, чтобы иконки по умолчанию были черными, можно сделать отдельный файл стилей, содержащий дефолтные настройки для каждой иконки. Это хороший способ сэкономить немного времени и стилизовать только отдельные иконки по мере необходимости.

Обращаясь к классу элемента svg, с помощью CSS можно указать нужный размер, изменить цвет, назначить эффект наведения, добавить анимацию, применить svg-фильтры.

Список свойств, доступных для изменения через CSS, есть на сайте W3C

Стилизация отдельных частей иконки

Но кое-что сделать все же можно.

Есть два способа, которыми можно добиться желаемого. И один из них даже имеет неплохую поддержку современными браузерами.

Предположим, что вам не требуется глубокая стилизация частей изображения, и вы вполне можете ограничиться двумя цветами. В этом случае, вполне можно обойтись использованием currentColor . Как говорится в спецификации о currentColor :

Это ключевое слово, содержащее значение свойства color. currentColor можно использовать в любых свойствах, принимающих значение color

То есть, если у нас есть элемент, в котором один и тот же цвет используется сразу в нескольких свойствах, достаточно указать его только один раз, а дальнейшее упоминание доверить ключевому слову currentColor :

Этот же прием, можно использовать в svg-спрайте. Предположим, нам необходимо раскрасить две части иконки в разные цвета. Удаляем атрибуты fill у тех элементов, что красятся в основной цвет средствами CSS. А в той части, которая планируется быть раскрашенной другим цветом – наоборот добавим атрибут fill , со значением currentColor . После этого, достаточно в CSS указать два значения: fill для цвета основной иконки и color для цвета ее второй части.

Как я уже упоминала выше, currentColor , на сегодняшний день, имеет неплохую поддержку всеми современными браузерами и IE11+. Если вам не требуется работа в старых версиях браузеров, смело можно брать этот прием на вооружение.

Есть и второй способ, гораздо более гибкий. В дело вступают CSS-переменные и здесь уже нет ограничений по количеству стилизуемых элементов. А принцип остается тот же: ко всем элементам, которые вы планируете изменять средствами CSS, добавляем нужные вам атрибуты.

В качестве значений указываем CSS-переменные, через которые и проводим стилизацию в CSS:

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

С поддержкой CSS-переменных дела обстоят немного хуже, в случае некоторых версий IE, Opera Mini и Android Browser, она отсутствует вовсе.

Вообще о стилизации svg элементов через use есть замечательная статья на английском, в которой очень подробно и с примерами изложена эта тема.

Использование внешней ссылки на спрайт

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

При таком способе подключения есть только один существенный недостаток – отсутствие кэширования спрайта. К счастью, эта проблема легко решаема. Внутри атрибута xlink:href достаточно прибавить к идентификатору путь, по которому расположен ваш спрайт:

Как уже упоминалось выше, элементу use совершенно все равно где находится нужный фрагмент, в теле документа или во внешнем файле. И все бы хорошо, если бы не всеми любимый браузер. IE, вплоть до одиннадцатой версии, не поддерживает использование внешней ссылки на спрайт в теге use . Но и это не проблема, так как есть замечательный скрипт под названием SVG for Everybody. Использовать его очень легко. Подключаем скрипт и делаем вызов, готово:

Этот скрипт добавляет поддержку ссылок на внешние svg-файлы не только в IE, но и в любых других браузерах, не поддерживающих подобный функционал.

Однако, несмотря на такую радужную картинку с подключением внешнего svg-спрайта, не спешите убирать его со страницы. Сейчас узнаете почему.

Очень распространенная ситуация, когда все вроде бы правильно, но не работает. Причин может быть множество и не всегда можно сразу увидеть, что не так. Начать нужно с проверки примеров, приведенных выше. Вставляете себе на страницу спрайт и выводите точно, как в примере, любую иконку. Если с этим проблем не возникло, следовательно что-то не так с вашим спрайтом.

Что же может не работать? Давайте рассмотрим несколько примеров.

Иконка не отображается совсем или отображается частично

Вставляем тэг use на страницу, а ничего не происходит. Если используете ссылку на внешний svg-файл – отключите и вставьте спрайт на страницу. Внимательно сверьте id символа иконки и атрибута xlink:href .

Попробуйте добавить в ваш спрайт одну из иконок, приведенных в примерах выше. Если она выводится без проблем, скорее всего проблема в ваших иконках. В этом случае, первое, что нужно сделать – это взять отдельную иконку и проверить в браузере. Если с отображением вне спрайта проблем нет, значит следует получше к ней присмотреться.

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

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

Обратите внимание, в этом коде мы видим блок defs , внутри которого определяется градиент для последующего использования внутри атрибута fill или любого другого атрибута. Этот внешний градиент и является, в нашем случае, корнем всех зол. Если вот этот код, не меняя, обернуть элементом symbol и добавить в спрайт, вы заработаете как минимум одну проблему, а возможно и больше.

Самая очевидная и известная проблема в браузере Firefox (версия 51.01). Независимо от того используете ли вы ссылку на внешний файл или встроили спрайт на страницу, он просто не отобразит градиент, находящийся внутри блока symbol . Есть один способ решения, люди советуют просто вынести блок defs c градиентом за пределы элемента symbol .

Это действительно поможет Firefox и не навредит остальным браузерам, но только лишь в том счастливом случае, если ваш спрайт присутствует на странице. Если же, вы используете внешнюю ссылку на спрайт, то после вышеуказанных манипуляций, вместо градиента иконка в IE (версия 11) приобретет сплошной черный цвет.

Далее, Chrome (версия 55) также, при использовании внешней ссылки на спрайт, проигнорирует градиент. И здесь тот же фокус, что и с Firefox уже не действует. Внятных объяснений такому поведению в хроме я не нашла. Если сталкивались с подобной проблемой и нашли решение, делитесь в комментариях.

Подводя итоги по градиентам, напрашивается довольно простой вывод. Если необходимо использовать иконки с градиентами в символьном svg-спрайте – не используйте ссылку на внешний файл, и выносите блок с градиентом за пределы symbol .

Не получается изменить цвет иконки

Здесь все довольно просто. Если иконка у вас выводится без проблем, но смена цвета средствами CSS не работает, скорее всего у какого-нибудь из внутренних элементов остались атрибуты fill , stroke или style . Еще раз проверьте всю разметку иконки на наличие оставшихся атрибутов. Даже если их не осталось в корневом элементе, они могут присутствовать в дочерних. После удаления их удаления проблема должна решиться.

Использование в качестве background-image

Я думаю, ни один верстальщик не любит лишней HTML-разметки. Инлайновый SVG это конечно хорошо и замечательно, но далеко не всегда удобно. Как же быть со старым добрым background-image? Думаю, правильным ответом на этот вопрос, будет «это невозможно». Но оказывается, все же возможно. Хотя придется, конечно, потрудиться.

Известно, что в качестве фона можно указывать внешний svg-файл. Поскольку код внутри symbol не отображается на странице, понадобиться комбинация из тегов view и use для каждой иконки.

То есть для каждой иконки, которую вы хотите использовать в качестве инлайнового svg и в качестве фона, нужно будет добавить вот такой код:

Обратите внимание на атрибуты viewbox и значение y элементов view и use . Начиная со второй иконки, нужно добавить сдвиг по оси y (или x ), чтобы иконки на наползали друг на друга. Модифицированный таким образом спрайт, можно увидеть на странице. После этого, можно ссылаться на иконку в свойстве background :

Как видите, технология пока сыровата, и полной поддержки браузерами не наблюдается. Сложно сказать, приживется ли она в будущем, но знать о такой возможности всегда полезно.

Автоматическая генерация спрайта

Если вы как и я, не любитель собирать спрайты вручную, можно автоматизировать этот процесс с помощью плагина gulp-svg-sprite. Плагин имеет множество опций и умеет не только символьные спрайты но и многие другие.

npm install gulp-svg-sprite

Редактируем gulpfile.js и создаем объект конфигурации, который в дальнейшем будем передавать плагину:

Свойство shape отвечает за настройки генерируемых svg-фигур. Здесь можно настраивать максимальные размеры, отступы, влиять на идентификаторы, которые генерируются автоматически и еще много чего.

В свойстве mode описываются виды спрайтов, которые требуется сгенерировать. Если нужно, можно указывать хоть все сразу, но мы остановимся на symbol . Указываем свойство dest , это папка для результирующего спрайта. В принципе, можно оставить это значение пустым. Тогда плагин по умолчанию создаст папку symbol а внутри нее папку svg и туда положит спрайт. У меня там точка, чтобы не создавать дополнительную папку symbol .

Создаем таск для спрайтов

Все просто, отдельные svg-иконки лежат в папке svg-separate . Указываем путь к ним, запускаем плагин с объектом конфигурации, и помещаем результат в папку sprites . Плагин генерирует id для элементов symbol из имен файлов svg-картинок. Поэтому, было бы неплохо давать им осмысленные имена, с тем чтобы не испытывать сложностей в дальнейшей работе.

Заключение

SVG-спрайты – прекрасная альтернатива растровым спрайтам и иконочным шрифтам. Даже не смотря на имеющиеся ограничения и небольшие проблемы, это определенно перспективная технология, которая улучшается с каждым днем. Не поленитесь потратить немного времени на ее изучение. В этой статье, я постаралась максимально подробно собрать и рассмотреть возможные проблемы при использовании символьных svg-спрайтов, а также способы их решения. Надеюсь, мой опыт будет вам полезен.

Такое дело в общем. Делаю проект со сборкой на gulp. Есть несколько svg-иконок, которые собираются в спрайт плагином "gulp-svg-sprite".
Одна из этих иконок выглядит так:

Однако после обработки этой и остальных иконок плагином "gulp-svg-sprite" она выглядит вот так:


Вот таск для обработки svg:

$.gp - это ссылка на "gulp-load-plugins"
И такой иконка становится не после плагина svgmin, я проверял.
В HTML подключаются иконки стандартно по id:

В спрайте несколько иконок и все они подключаются и отображаются корректно, кроме вот этой вот одной. Я понять не могу что с ней происходит и почему именно с ней.
Обратил только внимание на один момент.
Вот код исходного файла menu.svg

А это файл после обработки плагином gulp-svgmin:


Так вот, в исходнике эти самые полоски, которые потом пропадают, указываются в теге <line />
А после обработки плагином svgmin эти теги заменяются тегом <path />
Однако это всё равно не влияет на отображение иконки. Так как она деформируется уже после svg-sprite
Если нужно, то вот ссылка на этот самый собранный svg-sprite. Однако там весь код в одну строку и что-либо разобрать достаточно сложно.
Вот такая непонятная чертовщина происходит. Я конечно могу отдельно подключить этот файл и не морочить голову, но хочется всё таки разобраться в чём дело, чтобы дальше на подобных проблемах не останавливаться __________________
Помощь в написании контрольных, курсовых и дипломных работ здесь


Есть svg иконка, как узнать её path?
В интернете чаще всего работа с svg описана через тэг path. Рисую иконку в coreldrow. Как мне.

Обрезается svg-иконка
Есть 2 иконки в формате svg (googleplus и ВКонтакте). Вставляются в html-код идентично: &lt;p&gt;Войти.

Svg иконка, сбой на сайте
Кто нибудь знает где возможно посмотреть коллекцию svg иконок, тогда когда происходит ошибка на.

Решение

Для спрайта вся иконка должна быть как <path>, тогда будет корректно работать заливка. Перед варкой спрайта с помощью gulp, нужно просмотреть все иконки в иллюстраторе и с делать из них составные контуры (path).

SVG-спрайты

В очередной раз, просматривая вакансии на HTML-верстальщика, на предмет поиска темы для новой статьи, в списке требований работодателя, наткнулся на пункт – использовать в верстке SVG-спрайты.

Нам, верстальщикам, не стоит игнорировать требование работодателей, а идти в ногу с современными приёмами в верстке. Что по отдельности обозначают эти модные термины?

SVG – это масштабируемый формат векторной графики. В SVG формате хранится инструкция по построению изображения, по точкам и кривым, в виде текста. А это значит, что его можно открывать и редактировать в любом редакторе кода, работать с ним как с HTML файлом.

Спрайт – это один файл с графикой, состоящий из нескольких маленьких графических файлов, например иконок. Тогда, как SVG-спрайт – это масштабируемый один большой графический файл.

Почему SVG-спрайты – это хорошо?

Используя на сайте SVG-спрайты, вы убиваете сразу двух зайцев – получаете меньший вес у графики (SVG формат в разы легче, чем PNG и JPG) и меньше запросов к серверу.

<img src="icons/pinterest.jpg" alt="">
<img src="icons/twitter.jpg" alt="">
<img src="icons/facebook.jpg" alt="">

А здесь один запрос, при масштабирование векторная графика не теряет в качестве и меньше весит.

Как сделать SVG-спрайт?

  1. Скачиваем на сайте flaticon две иконки pinterest + github, в формате SVG. Теперь нужно два SVG-файла объединить в один.
  2. В редакторе кода создадим sprite.svg и пропишем следующий код.
    <svg display="none" xmlns="http://www.w3.org/2000/svg">
    <symbol viewBox="0 0 455.731 455.731">
    <g>
    <path ..здесь код отрисовки pinterest../>
    </g>
    </symbol>
    <symbol viewBox="0 0 512 512">
    <g>
    <path ..здесь код отрисовки github../>
    </g>
    </symbol>
    </svg>
  3. Значения атрибутов viewBox, копируем из pinterest.svg и github.svg.
  4. Открываем содержимое двух скачанных файлов и копируем внушительный код отрисовки иконки, тега path и вставляем между тегами <g></g>. Мы вынесли код иконок в отдельный файл sprite.svg.

Теперь, через CSS стили мы можем задавать иконкам любой цвет, размер, а также менять им цвет при наведении. Не стоит паниковать, если иконки не отображаются в Chrome на вашем компьютере, откройте другим браузером или загрузите страницу на сервер.

SVG-спрайты vs иконочных шрифтов

  • проще управлять позиционированием
  • удобнее делать многоцветные иконки
  • можно делать анимированные иконки

Поддержка браузерами

Формат SVG поддерживается всеми современными браузерами и начиная с
IE 11+.

Читайте также: