Чому спрайти взагалі вигідні? Тому що без спрайтів у вас завантажується кожна іконка окремо, на кожній новій сторінці, що части викликає проблему видимості завантаження, особливо при паганому інтернеті. Спрайт завантажується 1 раз, після відразу кешується, і всі іконки на всіх сторінках, будуть вже завантажені, що і спонукає багатьох розробників до їх використання.
Плюс, треба враховувати, якщо вам потрібно керувати кольором іконок, то SVG спрайти єдине правельне рішення.
Почнемо з азів, вам знадобиться модуль svg-sprite-generator.
Після його встановлення додайте до вашего watcher, або просто в package.json команду, яка буде збирати спрайт:
"scripts": {
"icons": "svg-sprite-generate -d ./assets/icons -o ./public/sprite.svg",
},
З наведенного прикладу, svg іконки знаходяться в папці assets/icons, а кластися спрайт буде в папку паблік.
Далі нам потрібно створити компонент, котрий буде чистати іконки з файлу, на прикаладі icon.vue:
<template lang="pug">
svg.v-icon(xmlns="http://www.w3.org/2000/svg" :width='size.w', :height='size.h', :class="'icon-'+ name")
use(:href="'/sprite.svg'+'#'+name" )
</template>
<script>
export default {
computed: {
size() {
const w = this.s && this.s.toString().includes(',') ? this.s.split(',')[0] : this.s || 32;
const h = this.s && this.s.toString().includes(',') ? this.s.split(',')[1] : this.s || 32;
return {
w: `${w}px`,
h: `${h}px`,
}
}
},
props: {
s: {
type: [String, Number],
default: 32
},
name: {
type: String,
require: true
}
}
}
</script>
Він достатньо простий, але це нам і потрібно.
Тепер до використання, в компонентах:
<template lang="pug">
div
icon(name="arrow-left" s="20,10")
</template
Модуль генерить іконки по назві файлу, тобто якщо файл називався arrow-left.svg, то так його потрібно і викликати. Модуль генерить спрайти в виді svg <symbol>
, тому тут є певні нюанси. Одним із такиї є неможливість використання додаткових стилів всередині файла, типу svg <defs>
, якщо такий буде в якомусь файлі іконки, то генератор взагалі не зможе сгенерувати спрайт. Вам доведеться вручну заходити в кожен файл іконок, та вичищати <defs>. Але це не є проблемою модулю, це є особливість svg symbol спрайтів.
Тепер у вас може постати питання, як керувати кольором, чи додати до іконки із спрайта градієнт, так як <defs> використовувати неможливо. Дуже просто. Вам потрібно вичистити з іконки, всі html tags, які відповідають за колір, тобто fill та stroke. Після очистки, файл іконки повинен вигядати приблизно так:
<svg width="26" height="26" viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg">
<path d="M13 26C20.1797 26 26 20.1797 26 13C26 5.8203 20.1797 0 13 0C5.8203 0 0 5.8203 0 13C0 20.1797 5.8203 26 13 26Z" fill-opacity="0.08" />
<path d="M7.68024 9.7501L6.66276 10.7676L12.9825 17.0873L14 16.0699L7.68024 9.7501Z" />
<path d="M11.9448 16.0708L12.9628 17.0889L19.2826 10.7691L18.2645 9.75104L11.9448 16.0708Z" />
</svg>
Ви можете використовувати не тільки path, а і rect, circle та будь що інше, це просто як для прикладу. Як ви бачите в іконці нема ніяких fill чи stroke, кольрами ви можете управляти через css напряму з вашого компонента. Наприклад:
<template lang="pug">
.component
icon.component__icon(name="arrow-left" s="20,10")
</template
<style lang="stylus">
.component
&__icon
fill green
stroke #FFA000
&:hover
stroke #000
</style>
З кольорами зрозуміло, але є ще градієнти, з цим трохи складніше. Вам потрібно підключити SVG gradient через <defs> напряму в ваш індексний файл, або файл леяута, я підключаю в app.vue:
<template lang="pug">
.g
RouterView(v-slot="{ Component }")
transition(:name="transitionName" )
component(:is="Component")
svg(style="width:0;height:0;position:absolute;" aria-hidden="true" focusable="false")
linearGradient#gradient(gradientTransform="rotate(65)")
stop(offset="0%" stop-color="#00c5ff")
stop(offset="100%" stop-color="#0095ff")
</template>
Таких ви можете підключити скільки завгодно, головне щоб в них був різний ID, в прикладі ID #gradient. Теперь через тіж самі стилі ви зможете додати і градієнт:
<template lang="pug">
.component
icon.component__icon(name="arrow-left" s="20,10")
</template
<style lang="stylus">
.component
&__icon
fill url(#gradient)
</style>
Це все. Щодо важливих нюансів. Деякі іконки можуть бути намальвані так, що якщо ви не задасте fill none, або stroke none, у вас будуть просто чорні квадрати, це вже залежить від дизайнера, якщо ви з таким зіткнулись, спробуйте задати іконці stoke: none, або fill: none.
На цьому точно все, дякую за увагу.