When developing, there are several benefits to using SVG sprites, but maintaining sprites can quickly become difficult and time-consuming. With Webpack and svg-sprite-loader
your sprite will be automatically generated when you bundle your code.
What is an SVG sprite?
A sprite is a collection of something, ex. images, put into a single file. This can be an advantage because a web page with many images may generate multiple server requests and can take a long time to load. Using image sprites will reduce the number of server requests and save bandwidth.
An SVG sprite is a file that contains several symbols/icons that can be used independently. Using a sprite like this gives some benefits for frontend development:
- it is simple to use,
- icons are reusable,
- it is possible to style the same icon with different colors in different places. Thus, you do not need separate SVG's with icons in different colors.
Installation and setup
A basic setup is fairly simple. Install svg-sprite-loader
with npm or yarn
# NPM
npm install svg-sprite-loader -D
# yarn
yarn add svg-sprite-loader -D
and create a separate rule for SVG's in your webpack config
module.exports = {
...
module: {
rules: [
{
test: /\.svg$/,
use: "svg-sprite-loader"
},
...
]
},
...
}
This will create a sprite within your bundled *.js
file. The svg-sprite-loader
transforms each imported SVG to a symbol within the sprite that has a unique id. By default this id is the same as the SVG filename.
Now you can import all the SVG's you need into your code and use them within an SVG tag with the SVG's id:
// *.js
import "/path/to/icons/logo.svg";
// *.html
<svg class="icon" aria-hidden="true">
<use xlink:href="#logo"></use>
</svg>
Styling the icons
The color of the icons can be set to the same color as the font with the styling fill: currentColor
. This will also make it possible to change the SVG color with the styling color
instead of fill
.
Advanced setup
I will not go into detail about the config for different setups, but other options are:
- creating multiple sprites by adding rules for different folders
- extract the sprite as a separate file from the bundle and set a different output path
- change the name of the sprite file with the
spriteFilename
option - change the name of icons with the
symbolId
option
Icon component
The generated sprite will only contain the SVG's that you import into your code. That means that if you forget to import a file you will not get an icon within the sprite and the svg will display an empty box.
If you are using a framework like Vue.js or React.js you might want to create an Icon component that imports all the icons you need. That way you know that all your svg's are in the sprite at all times, but that also means that you should tidy up your icons folder, so you don't import a lot of unused icons.
I use Vue.js and my Icon component looks something like this:
<template>
<svg :class="['icon', customClass]" aria-hidden="true">
<use :xlink:href="`#${iconName}`"></use>
</svg>
</template>
<script>
const requireAll = (requireContext) =>
requireContext.keys().map(requireContext);
const req = require.context("/path/to/icons", false, /\.svg$/);
requireAll(req);
export default {
props: {
iconName: {
type: String,
required: true
},
customClass: {
type: String,
default: ""
}
}
};
</script>
<style>
.icon {
width:20px;
height: 20px;
fill: currentColor
}
</style>
In our app or other components we can now import and use our Icon component like this:
<template>
...
<Icon iconName="logo" className="optionalClass" />
...
</template>
<script>
import Icon from 'path/to/component/Icon.vue'
export default {
components: {
...
Icon
},
...
};
</script>