Очередной блог фрилансера

коротко и полезно о веб-разработке

Menu Close

Символьный SVG-спрайт. Подробное руководство

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

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

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

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

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

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

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

 
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 64 64">
<path id="Cloud" fill="#42adf4" d="M48.147892,18.941c-1.2983971,0-2.5535965,0.1753006-3.7612991,0.4729996
	C40.9443932,15.4881001,35.9338951,13,30.3371944,13c-8.1797009,0-15.119194,5.2947998-17.6996002,12.6723003
	c-0.0374994-0.0002995-0.0735941-0.0056-0.1110992-0.0056C5.608295,25.6667004,0,31.3377991,0,38.3334007
	C0,45.3288994,5.608295,51,12.526495,51c3.0087996,0,32.4916,0,35.6213989,0C56.9027939,51,64,43.8232994,64,34.9705009
	C64,26.1175995,56.9027939,18.941,48.147892,18.941z M48.147892,48.9006004H12.526495
	c-5.749495,0-10.4271002-4.7404022-10.4271002-10.5671997c0-5.8087006,4.6484995-10.5377998,10.3733997-10.5672016
	c0.0489006,0.0031013,0.0979004,0.0051003,0.1476002,0.0055008l1.5026999,0.0123005l0.4962006-1.4185009
	c2.3568993-6.7385998,8.673399-11.2660999,15.7178993-11.2660999c4.7499981,0,9.2954998,2.0771008,12.4708042,5.6987
	l0.8415947,0.9598999l1.2396011-0.3055992c1.1086998-0.2733994,2.205101-0.4120007,3.2586975-0.4120007
	c7.5833015,0,13.7527008,6.2490005,13.7527008,13.9301014S55.7311935,48.9006004,48.147892,48.9006004z"/>
</svg>

<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 64 64">
<g id="Refresh_1_">
	<path fill="#42adf4" d="M48.7919998,22.6142502c-0.4766006,0-0.9570999,0.0224991-1.4336014,0.0664005
		c-2.7841988-7.0195007-9.6025848-11.6797009-17.2167988-11.6797009c-9.6581993,0-17.5868988,7.3096008-18.4403992,16.8076
		C5.1699009,28.2822495,0.0010008,33.7431488,0.0010008,40.3867493c0,6.9550018,5.6629996,12.6123009,12.6240005,12.6123009
		h36.1669998c8.3857002,0,15.2070007-6.8154984,15.2070007-15.1924019
		C63.9990005,29.4296494,57.1777,22.6142502,48.7919998,22.6142502z M48.7919998,51.0009499H12.625001
		c-5.8594003,0-10.6260004-4.7616997-10.6260004-10.6142006c0-5.8516006,4.7665997-10.6132984,10.6406002-10.6132984
		c0.5362139,0,0.9765997-0.4229012,0.9990997-0.9580002c0.3603001-8.8691998,7.6093006-15.8164005,16.5028992-15.8164005
		c7.0342159,0,13.3076,4.4589996,15.6093998,11.0946999c0.1581993,0.4550991,0.6268997,0.7313995,1.089817,0.6620998
		c0.6444817-0.0946999,1.3007812-0.1434994,1.9511833-0.1434994c7.2831993,0,13.2089996,5.9188995,13.2089996,13.1942978
		S56.0751991,51.0009499,48.7919998,51.0009499z"/>
	<path fill="#42adf4" d="M32.4968147,25.40415l0.7804871-0.6707001c0.4189987-0.3603992,0.4667969-0.9913006,0.1075134-1.4102001
		c-0.3604164-0.419899-0.9922142-0.4657993-1.4102154-0.107399l-2.8262005,2.4277
		c-0.4188995,0.3603992-0.4667988,0.9911995-0.107399,1.4101982l2.4277,2.8271008
		c0.1982994,0.2304993,0.4776001,0.3486004,0.7588005,0.3486004c0.2314987,0,0.4628983-0.0790997,0.6513977-0.2411995
		c0.4189148-0.3603001,0.4668007-0.9912014,0.1074028-1.4101009l-1.0659008-1.2411003
		c3.7255001,0.3786011,6.6420994,3.5335007,6.6420994,7.3573017c0,4.0780983-3.3174019,7.3964996-7.3955002,7.3964996
		s-7.3955002-3.3184013-7.3955002-7.3964996c0-0.5527-0.4473-1-1-1c-0.5527992,0-1,0.4473-1,1
		c0,5.1815987,4.2147999,9.3964996,9.3955002,9.3964996c5.1805992,0,9.3955002-4.214901,9.3955002-9.3964996
		C40.5625,29.9661503,37.0483017,26.0535507,32.4968147,25.40415z"/>
		</g>
</svg>

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

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <symbol id="cloud" viewBox="0 0 64 64">
        <path id="cloud" fill="#42adf4"  d="M48.147892,18.941c-1.2983971,0-2.5535965,0.1753006-3.7612991,0.4729996
        	C40.9443932,15.4881001,35.9338951,13,30.3371944,13c-8.1797009,0-15.119194,5.2947998-17.6996002,12.6723003
        	c-0.0374994-0.0002995-0.0735941-0.0056-0.1110992-0.0056C5.608295,25.6667004,0,31.3377991,0,38.3334007
        	C0,45.3288994,5.608295,51,12.526495,51c3.0087996,0,32.4916,0,35.6213989,0C56.9027939,51,64,43.8232994,64,34.9705009
        	C64,26.1175995,56.9027939,18.941,48.147892,18.941z M48.147892,48.9006004H12.526495
        	c-5.749495,0-10.4271002-4.7404022-10.4271002-10.5671997c0-5.8087006,4.6484995-10.5377998,10.3733997-10.5672016
        	c0.0489006,0.0031013,0.0979004,0.0051003,0.1476002,0.0055008l1.5026999,0.0123005l0.4962006-1.4185009
        	c2.3568993-6.7385998,8.673399-11.2660999,15.7178993-11.2660999c4.7499981,0,9.2954998,2.0771008,12.4708042,5.6987
        	l0.8415947,0.9598999l1.2396011-0.3055992c1.1086998-0.2733994,2.205101-0.4120007,3.2586975-0.4120007
        	c7.5833015,0,13.7527008,6.2490005,13.7527008,13.9301014S55.7311935,48.9006004,48.147892,48.9006004z"/>
    </symbol>

    <symbol id="cloud-computing" viewBox="0 0 64 64">
        <g id="Refresh_1_">
            <path fill="#42adf4" d="M48.7919998,22.6142502c-0.4766006,0-0.9570999,0.0224991-1.4336014,0.0664005
        		c-2.7841988-7.0195007-9.6025848-11.6797009-17.2167988-11.6797009c-9.6581993,0-17.5868988,7.3096008-18.4403992,16.8076
        		C5.1699009,28.2822495,0.0010008,33.7431488,0.0010008,40.3867493c0,6.9550018,5.6629996,12.6123009,12.6240005,12.6123009
        		h36.1669998c8.3857002,0,15.2070007-6.8154984,15.2070007-15.1924019
        		C63.9990005,29.4296494,57.1777,22.6142502,48.7919998,22.6142502z M48.7919998,51.0009499H12.625001
        		c-5.8594003,0-10.6260004-4.7616997-10.6260004-10.6142006c0-5.8516006,4.7665997-10.6132984,10.6406002-10.6132984
        		c0.5362139,0,0.9765997-0.4229012,0.9990997-0.9580002c0.3603001-8.8691998,7.6093006-15.8164005,16.5028992-15.8164005
        		c7.0342159,0,13.3076,4.4589996,15.6093998,11.0946999c0.1581993,0.4550991,0.6268997,0.7313995,1.089817,0.6620998
        		c0.6444817-0.0946999,1.3007812-0.1434994,1.9511833-0.1434994c7.2831993,0,13.2089996,5.9188995,13.2089996,13.1942978
        		S56.0751991,51.0009499,48.7919998,51.0009499z"/>
            <path fill="#42adf4" d="M32.4968147,25.40415l0.7804871-0.6707001c0.4189987-0.3603992,0.4667969-0.9913006,0.1075134-1.4102001
        		c-0.3604164-0.419899-0.9922142-0.4657993-1.4102154-0.107399l-2.8262005,2.4277
        		c-0.4188995,0.3603992-0.4667988,0.9911995-0.107399,1.4101982l2.4277,2.8271008
        		c0.1982994,0.2304993,0.4776001,0.3486004,0.7588005,0.3486004c0.2314987,0,0.4628983-0.0790997,0.6513977-0.2411995
        		c0.4189148-0.3603001,0.4668007-0.9912014,0.1074028-1.4101009l-1.0659008-1.2411003
        		c3.7255001,0.3786011,6.6420994,3.5335007,6.6420994,7.3573017c0,4.0780983-3.3174019,7.3964996-7.3955002,7.3964996
        		s-7.3955002-3.3184013-7.3955002-7.3964996c0-0.5527-0.4473-1-1-1c-0.5527992,0-1,0.4473-1,1
        		c0,5.1815987,4.2147999,9.3964996,9.3955002,9.3964996c5.1805992,0,9.3955002-4.214901,9.3955002-9.3964996
        		C40.5625,29.9661503,37.0483017,26.0535507,32.4968147,25.40415z"/>
        </g>
    </symbol>
</svg>

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

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

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

<svg class="inline-svg-icon">
  <use xlink:href="#cloud"></use>
</svg>

<svg class="inline-svg-icon">
  <use xlink:href="#cloud-computing"></use>
</svg>

See the Pen Symbol SVG Sprite detail guide — simple SVG sprite example by dreamhelg (@dreamhelg) on CodePen.dark

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

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

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <symbol id="cloud" viewBox="0 0 64 64">
        <path id="cloud" d="M48.147892,18.941c-1.2983971,0-2.5535965,0.1753006-3.7612991,0.4729996
        	C40.9443932,15.4881001,35.9338951,13,30.3371944,13c-8.1797009,0-15.119194,5.2947998-17.6996002,12.6723003
        	c-0.0374994-0.0002995-0.0735941-0.0056-0.1110992-0.0056C5.608295,25.6667004,0,31.3377991,0,38.3334007
        	C0,45.3288994,5.608295,51,12.526495,51c3.0087996,0,32.4916,0,35.6213989,0C56.9027939,51,64,43.8232994,64,34.9705009
        	C64,26.1175995,56.9027939,18.941,48.147892,18.941z M48.147892,48.9006004H12.526495
        	c-5.749495,0-10.4271002-4.7404022-10.4271002-10.5671997c0-5.8087006,4.6484995-10.5377998,10.3733997-10.5672016
        	c0.0489006,0.0031013,0.0979004,0.0051003,0.1476002,0.0055008l1.5026999,0.0123005l0.4962006-1.4185009
        	c2.3568993-6.7385998,8.673399-11.2660999,15.7178993-11.2660999c4.7499981,0,9.2954998,2.0771008,12.4708042,5.6987
        	l0.8415947,0.9598999l1.2396011-0.3055992c1.1086998-0.2733994,2.205101-0.4120007,3.2586975-0.4120007
        	c7.5833015,0,13.7527008,6.2490005,13.7527008,13.9301014S55.7311935,48.9006004,48.147892,48.9006004z"/>
    </symbol>

    <symbol id="cloud-computing" viewBox="0 0 64 64">
        <g id="Refresh_1_">
            <path d="M48.7919998,22.6142502c-0.4766006,0-0.9570999,0.0224991-1.4336014,0.0664005
        		c-2.7841988-7.0195007-9.6025848-11.6797009-17.2167988-11.6797009c-9.6581993,0-17.5868988,7.3096008-18.4403992,16.8076
        		C5.1699009,28.2822495,0.0010008,33.7431488,0.0010008,40.3867493c0,6.9550018,5.6629996,12.6123009,12.6240005,12.6123009
        		h36.1669998c8.3857002,0,15.2070007-6.8154984,15.2070007-15.1924019
        		C63.9990005,29.4296494,57.1777,22.6142502,48.7919998,22.6142502z M48.7919998,51.0009499H12.625001
        		c-5.8594003,0-10.6260004-4.7616997-10.6260004-10.6142006c0-5.8516006,4.7665997-10.6132984,10.6406002-10.6132984
        		c0.5362139,0,0.9765997-0.4229012,0.9990997-0.9580002c0.3603001-8.8691998,7.6093006-15.8164005,16.5028992-15.8164005
        		c7.0342159,0,13.3076,4.4589996,15.6093998,11.0946999c0.1581993,0.4550991,0.6268997,0.7313995,1.089817,0.6620998
        		c0.6444817-0.0946999,1.3007812-0.1434994,1.9511833-0.1434994c7.2831993,0,13.2089996,5.9188995,13.2089996,13.1942978
        		S56.0751991,51.0009499,48.7919998,51.0009499z"/>
            <path d="M32.4968147,25.40415l0.7804871-0.6707001c0.4189987-0.3603992,0.4667969-0.9913006,0.1075134-1.4102001
        		c-0.3604164-0.419899-0.9922142-0.4657993-1.4102154-0.107399l-2.8262005,2.4277
        		c-0.4188995,0.3603992-0.4667988,0.9911995-0.107399,1.4101982l2.4277,2.8271008
        		c0.1982994,0.2304993,0.4776001,0.3486004,0.7588005,0.3486004c0.2314987,0,0.4628983-0.0790997,0.6513977-0.2411995
        		c0.4189148-0.3603001,0.4668007-0.9912014,0.1074028-1.4101009l-1.0659008-1.2411003
        		c3.7255001,0.3786011,6.6420994,3.5335007,6.6420994,7.3573017c0,4.0780983-3.3174019,7.3964996-7.3955002,7.3964996
        		s-7.3955002-3.3184013-7.3955002-7.3964996c0-0.5527-0.4473-1-1-1c-0.5527992,0-1,0.4473-1,1
        		c0,5.1815987,4.2147999,9.3964996,9.3955002,9.3964996c5.1805992,0,9.3955002-4.214901,9.3955002-9.3964996
        		C40.5625,29.9661503,37.0483017,26.0535507,32.4968147,25.40415z"/>
        </g>
    </symbol>
</svg>

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

  .inline-svg-icon{
       display: inline-block;
       width: 150px;
       height: 150px;
       fill: #7db958;
       margin-right: 30px;
   }

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

See the Pen Symbol SVG Sprite detail guide — SVG sprite with CSS styling by dreamhelg (@dreamhelg) on CodePen.dark

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

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

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

Все дело в теге use, с помощью которого мы встраиваем иконку на страницу. Фактически, use вставляет на страницу не саму иконку, а копию именованной области на которую мы ссылаемся в атрибуте xlink:href. Где бы эта область не находилась (на этой же странице или во внешнем файле), тег use найдет ее и скопирует. При этом код иконки не станет частью документа, а будет помещен в теневой DOM. Поэтому, можно сколько угодно назначать классы отдельным частям иконки — результат останется прежним. Ограничения теневого DOM не дадут стилизовать внутренние части изображения.

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

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

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

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

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

h1{
       color: aquamarine;
       box-shadow: 3px 2px 1px 20px currentColor;
       text-shadow: 3px 2px 1px currentColor;
       border-bottom: solid 2px currentColor;
}

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

<symbol id="cloud-computing" viewBox="0 0 64 64">
        <g id="Refresh_1_">
            <path d="M48.7919998,22.6142502c-0.4766006,0-0.9570999,0.0224991-1.4336014,0.0664005
        		c-2.7841988-7.0195007-9.6025848-11.6797009-17.2167988-11.6797009c-9.6581993,0-17.5868988,7.3096008-18.4403992,16.8076
        		C5.1699009,28.2822495,0.0010008,33.7431488,0.0010008,40.3867493c0,6.9550018,5.6629996,12.6123009,12.6240005,12.6123009
        		h36.1669998c8.3857002,0,15.2070007-6.8154984,15.2070007-15.1924019
        		C63.9990005,29.4296494,57.1777,22.6142502,48.7919998,22.6142502z M48.7919998,51.0009499H12.625001
        		c-5.8594003,0-10.6260004-4.7616997-10.6260004-10.6142006c0-5.8516006,4.7665997-10.6132984,10.6406002-10.6132984
        		c0.5362139,0,0.9765997-0.4229012,0.9990997-0.9580002c0.3603001-8.8691998,7.6093006-15.8164005,16.5028992-15.8164005
        		c7.0342159,0,13.3076,4.4589996,15.6093998,11.0946999c0.1581993,0.4550991,0.6268997,0.7313995,1.089817,0.6620998
        		c0.6444817-0.0946999,1.3007812-0.1434994,1.9511833-0.1434994c7.2831993,0,13.2089996,5.9188995,13.2089996,13.1942978
        		S56.0751991,51.0009499,48.7919998,51.0009499z"/>
            <path fill="currentColor" d="M32.4968147,25.40415l0.7804871-0.6707001c0.4189987-0.3603992,0.4667969-0.9913006,0.1075134-1.4102001
        		c-0.3604164-0.419899-0.9922142-0.4657993-1.4102154-0.107399l-2.8262005,2.4277
        		c-0.4188995,0.3603992-0.4667988,0.9911995-0.107399,1.4101982l2.4277,2.8271008
        		c0.1982994,0.2304993,0.4776001,0.3486004,0.7588005,0.3486004c0.2314987,0,0.4628983-0.0790997,0.6513977-0.2411995
        		c0.4189148-0.3603001,0.4668007-0.9912014,0.1074028-1.4101009l-1.0659008-1.2411003
        		c3.7255001,0.3786011,6.6420994,3.5335007,6.6420994,7.3573017c0,4.0780983-3.3174019,7.3964996-7.3955002,7.3964996
        		s-7.3955002-3.3184013-7.3955002-7.3964996c0-0.5527-0.4473-1-1-1c-0.5527992,0-1,0.4473-1,1
        		c0,5.1815987,4.2147999,9.3964996,9.3955002,9.3964996c5.1805992,0,9.3955002-4.214901,9.3955002-9.3964996
        		C40.5625,29.9661503,37.0483017,26.0535507,32.4968147,25.40415z"/>
        </g>
    </symbol>
.cloud-computing{
   fill: #103f6f;
   color: #6fb1f5;
}

See the Pen Symbol SVG Sprite detail guide — SVG sprite coloring in two colors with CSS by dreamhelg (@dreamhelg) on CodePen.dark

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

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

<symbol id="browser" viewBox="0 0 64 64">
        <g>
            <path fill="var(--star-fill)" d="M25.0956993,39.8096008L24.2402,46.8065987c-0.0429993,0.3487015,0.1074009,0.6944008,0.392601,0.9014015
		c0.1679993,0.1221008,0.3680992,0.1846008,0.5692997,0.1846008c0.1386986,0,0.2793121-0.0293007,0.4091988-0.089901L32,44.8261986
		L38.3895988,47.8027c0.3194008,0.1474991,0.6944008,0.1114006,0.9785004-0.0946999
		c0.285202-0.2070007,0.4356003-0.5527,0.392601-0.9023018l-0.8563995-6.9960976l4.8046989-5.157299
		c0.1669006-0.1787033,0.2597008-0.4150009,0.2597008-0.6601028c0-0.7987976,0-0.7987976-4.4648018-1.6689987L36.2666016,31.6924
		l-3.4190025-6.1620998C32.6767006,25.2217007,32.3525009,25.0312004,32,25.0312004
		c-0.3525887,0-0.6767998,0.1905003-0.8477001,0.4990997L27.7334118,31.6924l-6.9190006,1.3486004
		c-0.3457108,0.0673981-0.6269112,0.3163986-0.736311,0.6514015c-0.1084003,0.3348999-0.0272999,0.7030983,0.2129002,0.9598999
		L25.0956993,39.8096008z M28.5468006,33.5088005c0.2803001-0.0546989,0.5234985-0.2304993,0.662199-0.4814987L32,27.9971008
		l2.7900009,5.030201c0.1386986,0.2509995,0.3817978,0.4267998,0.6620979,0.4814987c0,0,3.4756012,0.6767006,5.6485023,1.1006012
		l-3.9219017,4.2098999c-0.1952858,0.2089996-0.2881012,0.4941978-0.2528992,0.7783966L37.625,45.3075981l-5.2158012-2.4296989
		C32.2793007,42.8184013,32.1395988,42.7881012,32,42.7881012c-0.1396999,0-0.2793007,0.0303001-0.4092007,0.089798
		l-5.2148991,2.4296989l0.6982994-5.7108994c0.0351009-0.2831993-0.0576-0.5683975-0.2528992-0.7773972l-3.9218884-4.2098999
		L28.5468006,33.5088005z"/>
            <path d="M60,5h-56C1.7908008,5,0.0000008,6.7908001,0.0000008,9v5v2v39c0,2.2090988,1.7908,4,3.9999998,4h56
		c2.2090988,0,4-1.7909012,4-4V16v-2V9C64,6.7908001,62.2090988,5,60,5z M62,55c0,1.1027985-0.8972015,2-2,2h-56
		c-1.1027997,0-1.9999998-0.8972015-1.9999998-2V16h60V55z M62,14h-60V9c0-1.1027999,0.8972001-2,1.9999998-2h56
		c1.1027985,0,2,0.8972001,2,2V14z"/>
            <path fill="var(--dot-left)" d="M6.0000005,9c-0.9649997,0-1.75,0.7849998-1.75,1.75c0,0.9649,0.7850003,1.75,1.75,1.75c0.9649,0,1.75-0.7851,1.75-1.75
		C7.7500005,9.7849998,6.9649005,9,6.0000005,9z M6.0000005,11.5c-0.4141998,0-0.75-0.3358002-0.75-0.75s0.3358002-0.75,0.75-0.75
		c0.4142003,0,0.75,0.3358002,0.75,0.75S6.4142008,11.5,6.0000005,11.5z"/>
            <path fill="var(--dot-right)" d="M16,9c-0.9649992,0-1.75,0.7849998-1.75,1.75c0,0.9649,0.7850008,1.75,1.75,1.75c0.964901,0,1.75-0.7851,1.75-1.75
		C17.75,9.7849998,16.964901,9,16,9z M16,11.5c-0.4141998,0-0.75-0.3358002-0.75-0.75S15.5858002,10,16,10s0.75,0.3358002,0.75,0.75
		S16.4141998,11.5,16,11.5z"/>
            <path fill="var(--dot-center)" d="M11.000001,9c-0.9650002,0-1.75,0.7849998-1.75,1.75c0,0.9649,0.7849998,1.75,1.75,1.75c0.9649,0,1.75-0.7851,1.75-1.75
		C12.750001,9.7849998,11.964901,9,11.000001,9z M11.000001,11.5c-0.4142008,0-0.75-0.3358002-0.75-0.75s0.3357992-0.75,0.75-0.75
		c0.4141998,0,0.75,0.3358002,0.75,0.75S11.4142008,11.5,11.000001,11.5z"/>
        </g>
    </symbol>

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

.browser{
   width: 250px;
   height: 250px;
   fill: #89edcd;
    
  //CSS-переменные, в коде SVG-иконки
   --star-fill: #f3eb04;
   --dot-left: #f6214e;
   --dot-center: #2153f6;
   --dot-right: #53f621;
}

See the Pen Symbol SVG Sprite detail guide — SVG sprite coloring in many colors with CSS Variables by dreamhelg (@dreamhelg) on CodePen.dark

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

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

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

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

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

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

<svg class="inline-svg-icon browser">
  <use xlink:href="sprite-manual.svg#browser"></use>
</svg>

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


<script src="/path/to/svg4everybody.js"></script>
<script>svg4everybody();</script>

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

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

«Я все сделал как в статье, а у меня не работает»

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

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

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

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

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

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

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

<?xml version="1.0" encoding="UTF-8"?>
<svg width="83px" height="70px" viewBox="0 0 83 70" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: sketchtool 42 (36781) - http://www.bohemiancoding.com/sketch -->
    <title>68284BF1-E5AB-4CFC-9D01-D12772182903</title>
    <desc>Created with sketchtool.</desc>
    <defs>
        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
            <stop stop-color="#B7E351" offset="0%"></stop>
            <stop stop-color="#96C226" offset="100%"></stop>
        </linearGradient>
        <path d="M58,54.8873365 C72.0133163,53.6213679 83,41.8430042 83,27.5 C83,12.30883 70.6906485,0 55.5062939,0 L27.4937061,0 C12.3139475,0 0,12.3121694 0,27.5 C0,42.69117 12.3155587,55 27.5075703,55 L38.4840531,55 L39.25,55 L58,70 L58,54.8873365 Z" id="path-2"></path>
        <mask id="mask-3" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="83" height="70" fill="white">
            <use xlink:href="#path-2"></use>
        </mask>
        <rect id="path-4" x="19" y="31" width="21" height="2"></rect>
        <mask id="mask-5" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="21" height="2" fill="white">
            <use xlink:href="#path-4"></use>
        </mask>
        <rect id="path-6" x="19" y="21" width="42" height="2"></rect>
        <mask id="mask-7" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="42" height="2" fill="white">
            <use xlink:href="#path-6"></use>
        </mask>
    </defs>
    <g id="ОС---Компания" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <g id="О-нас" transform="translate(-427.000000, -6104.000000)" stroke-width="4">
            <g id="СПРАВКА" transform="translate(0.000000, 5975.000000)">
                <g id="Иконка" transform="translate(427.000000, 129.000000)">
                    <use id="Combined-Shape" stroke="url(#linearGradient-1)" mask="url(#mask-3)" xlink:href="#path-2"></use>
                    <use id="Rectangle-251" stroke="#A2D136" mask="url(#mask-5)" xlink:href="#path-4"></use>
                    <use id="Rectangle-251" stroke="#A2D136" mask="url(#mask-7)" xlink:href="#path-6"></use>
                </g>
            </g>
        </g>
    </g>
</svg>

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

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

<symbol id="instagram" viewBox="0 0 42 42">
        <title>AE825A6C-57C0-4A3E-AE27-3FEDBA635E69</title>
        <desc>Created with sketchtool.</desc>
        <g id="ОС---Общее" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
            <g id="Главная-страница-Красота" transform="translate(-959.000000, -4630.000000)" fill="url(#radialGradient-1)">
                <g id="Присоединяйтесь" transform="translate(378.000000, 4513.000000)">
                    <g id="Group-2" transform="translate(0.000000, 88.000000)">
                        <path d="M617,40 C617,41.6570313 615.656641,43 614,43 C612.343359,43 611,41.6570313 611,40 C611,38.3429687 612.343359,37 614,37 C615.657031,37 617,38.3429687 617,40 L617,40 Z M602,57 C598.133971,57 595,53.8660292 595,50 C595,46.1339708 598.133971,43 602,43 C605.866029,43 609,46.1339708 609,50 C609,53.8660292 605.866029,57 602,57 L602,57 Z M602,39 C595.924814,39 591,43.9248136 591,50 C591,56.0751864 595.924814,61 602,61 C608.075186,61 613,56.0751864 613,50 C613,43.9248136 608.075186,39 602,39 L602,39 Z M602.000162,33 C607.53696,33 608.192731,33.0210599 610.379068,33.1208512 C612.400814,33.2131905 613.498842,33.5507962 614.229457,33.8349422 C615.197238,34.2111036 615.888002,34.6604885 616.613757,35.3862434 C617.339512,36.1116744 617.788896,36.8024376 618.165058,37.7705429 C618.44888,38.5011578 618.786809,39.5991862 618.879149,41.6209322 C618.97894,43.807593 619,44.4633644 619,50.000162 C619,55.5369596 618.97894,56.192731 618.879149,58.3790678 C618.786809,60.4008138 618.449204,61.4988422 618.165058,62.2294571 C617.788896,63.1972384 617.339512,63.8880016 616.613757,64.6137566 C615.888326,65.3395115 615.197562,65.7888964 614.229457,66.1650578 C613.498842,66.4488798 612.400814,66.7868095 610.379068,66.8791488 C608.192731,66.9789401 607.53696,67 602.000162,67 C596.46304,67 595.807269,66.9789401 593.620932,66.8791488 C591.599186,66.7868095 590.501158,66.4492038 589.770543,66.1650578 C588.802762,65.7888964 588.111998,65.3395115 587.386243,64.6137566 C586.660812,63.8883256 586.211104,63.1975624 585.834942,62.2294571 C585.55112,61.4988422 585.213191,60.4008138 585.120851,58.3790678 C585.02106,56.192407 585,55.5366356 585,50.000162 C585,44.4633644 585.02106,43.807593 585.120851,41.6209322 C585.213191,39.5991862 585.550796,38.5011578 585.834942,37.7705429 C586.211104,36.8027616 586.660488,36.1119984 587.386243,35.3862434 C588.111674,34.6604885 588.802438,34.2111036 589.770543,33.8349422 C590.501158,33.5511202 591.599186,33.2131905 593.620932,33.1208512 C595.807593,33.0210599 596.463364,33 602.000162,33 L602.000162,33 Z M602,29 C596.296859,29 595.581547,29.0242813 593.341766,29.1263281 C591.106578,29.228375 589.579813,29.5834062 588.244344,30.1025 C586.863266,30.6389844 585.692188,31.35725 584.524719,32.5247187 C583.35725,33.6921875 582.638984,34.8632656 582.1025,36.2443437 C581.583406,37.5801406 581.228375,39.1065781 581.126328,41.3417656 C581.024281,43.5815469 581,44.2968594 581,50 C581,55.7031406 581.024281,56.4184531 581.126328,58.6582344 C581.228375,60.8934219 581.583406,62.4198594 582.1025,63.7556563 C582.638984,65.1367344 583.35725,66.3078125 584.524719,67.4752812 C585.692188,68.64275 586.863266,69.3606875 588.244344,69.8975 C589.580141,70.4165938 591.106578,70.771625 593.341766,70.8736719 C595.581547,70.9757187 596.296859,71 602,71 C607.703141,71 608.418453,70.9757187 610.658234,70.8736719 C612.893422,70.771625 614.419859,70.4165938 615.755656,69.8975 C617.136734,69.3606875 618.307812,68.64275 619.475281,67.4752812 C620.64275,66.3078125 621.360688,65.1367344 621.8975,63.7556563 C622.416594,62.4198594 622.771625,60.8934219 622.873672,58.6582344 C622.975719,56.4184531 623,55.7031406 623,50 C623,44.2968594 622.975719,43.5815469 622.873672,41.3417656 C622.771625,39.1065781 622.416594,37.5801406 621.8975,36.2443437 C621.360688,34.8632656 620.64275,33.6921875 619.475281,32.5247187 C618.307812,31.35725 617.136734,30.6393125 615.755656,30.1025 C614.419859,29.5834062 612.893422,29.228375 610.658234,29.1263281 C608.418453,29.0242813 607.703141,29 602,29 L602,29 Z" id="Instagram"></path>
                    </g>
                </g>
            </g>
        </g>
    </symbol>

    <defs>
        <radialGradient cx="14.9305469%" cy="100.347188%" fx="14.9305469%" fy="100.347188%" r="127.774922%" id="radialGradient-1">
            <stop stop-color="#FFB140" offset="0%"></stop>
            <stop stop-color="#FF5445" offset="25.59%"></stop>
            <stop stop-color="#FC2B82" offset="59.9%"></stop>
            <stop stop-color="#8E40B7" offset="100%"></stop>
        </radialGradient>
    </defs>

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

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

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

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

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

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

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

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

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

 
    <view id="cloud-view" viewBox="0 0 64 64" />
    <view id="cloud-computing-view" viewBox="0 60 64 64" />
   
    <use xlink:href="#cloud" width="64" height="64" x="0" y="0"></use>
    <use xlink:href="#cloud-computing" width="64" height="64" x="0" y="60"></use>

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

.sprite-background-icon{
    width: 150px;
    height: 150px;
    display: inline-block;
    margin-right: 30px;
}

.cloud{
    background: url('sprite-remote.svg#cloud-view') top left no-repeat;
}

.cloud-computing{
    background: url('sprite-remote.svg#cloud-computing-view') top left no-repeat;
}

See the Pen Symbol SVG Sprite detail guide — SVG sprite symbol in background-image by dreamhelg (@dreamhelg) on CodePen.dark

И о чудо, действительно картинка выводится в фоне и масштабируется исходя из размеров блока. Плохие новости – управлять цветом через CSS не получится. При острой необходимости, можно создать для одной и той же иконки несколько вариантов view и use, атрибутами style, где указать разные варианты цветов. Браузеры Firefox, Chrome, IE11 – все работает. Есть информация, что не работает в Safari.

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

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

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

Ставим плагин

npm install gulp-svg-sprite

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

var gulp = require('gulp'),
    svgSprite = require('gulp-svg-sprite');

var config = {
    shape: {
        dimension: {         // Set maximum dimensions
            maxWidth: 500,
            maxHeight: 500
        },
        spacing: {         // Add padding
            padding: 0
        }
    },
    mode: {
        symbol: {
            dest : '.'
        }
    }
};

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

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

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

gulp.task('svg-sprite', function (cb) {
    return gulp.src('svg-separate/*.svg')
        .pipe(svgSprite(config))
        .pipe(gulp.dest('sprites'));
});

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

Заключение

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

Автор svg-иконок из примеров — Elias Bikbulatov

Рассказать друзьям

Понравилась статья? Лучший способ сказать спасибо - поделиться ссылкой в социальных сетях: