
While there are many icon libraries that you can use in your Vue.js project, sometimes it becomes necessary to use custom SVG icons.
Rather than displaying the icons using the <img>
tag, the best way to use SVG icons in a Vue.js project is to use them as Vue.js components. This gives you the flexibility of being able to change the icon color and manipulate other of its properties on the go.
To achieve this, you need to install an SVG loader in your project;
yarn add -D vue-svg-loader vue-template-compiler
// OR
npm i -D vue-svg-loader vue-template-compiler
Then you need to tell Webpack to use the just installed vue-svg-loader
to load SVG files.
Add the following to your Webpack rules
property;
module: {
rules: [
// ...
{
test: /\.svg$/i,
oneOf: [
{
resourceQuery: /inline/,
use: [
{
loader: 'vue-svg-loader',
options: { svgo: false },
},
],
},
]
},
]
}
Here we are using the resourceQuery
property to tell Webpack when to use the vue-svg-loader
to load SVG files. So unless we append ?inline
to the filename when importing an SVG file, this loader will not be used. This is useful in cases where you need to treat some SVG images as regular files.
If you are using Nuxt.js
You just need to install the @nuxt/svg
instead. This module already has the above configuration set.
yarn add -D @nuxt/svg
// OR
npm i -D @nuxtjs/svg
And add it to your nuxt.config.js
file;
// nuxt.config.js
export default {
buildModules: ["@nuxtjs/svg"],
};
Now to use a custom SVG icon in any of your components, you can import it as follows;
<template>
<nav>
<a href="https://github.com/vuejs/vue">
<VueLogo class="logo" />
Vue
</a>
</nav>
</template>
<script>
import VueLogo from './public/vue.svg?inline';
export default {
components: {
VueLogo,
},
};
</script>
<style scoped>
.logo {
width: 28px;
height: 28px;
margin-right: 10px;
}
</style>
Creating An Icon Component
If you are going to be using a lot of icons in your project, importing them individually is not ideal. So let's create a generic <Icon>
component that we can easily use to import our icons.
// components/Icon.vue
<script>
export default {
props: {
name: {
type: String,
required: true,
},
},
render(createElement) {
try {
const component = require(`~/assets/icons/${this.name}.svg?inline`)
const data = {
class: ['icon'],
}
const children = [createElement(component)]
return createElement('span', data, children)
} catch(e) {
// console.log(this.name, e)
return null
}
},
}
</script>
<style lang="scss">
.icon {
display: inline-block;
> svg {
width: 1em;
height: 1em;
margin-top: -4px;
fill: currentColor;
}
}
</style>
The component uses the require
function to load up SVG files from the assets/icons
folder, it then wraps the imported SVG component in a span
element which we use to apply some styles to the icons.
The component accepts a required name
prop, which is the name of the SVG file we want to load, placed in the assets/icons
folder.
Don't forget to register the component;
import Icon from 'components/Icon.vue'
Vue.component('Icon', Icon)
Now, all we need to do is add all our SVG icons to the assets/icons
folder. And when you need to use anyone of them, you can easily use the Icon
component to load them.
For example, if we have an SVG file with name vue.svg
in our assets/icons
folder, we can use it in our project as follows;
<Icon name="vue" />
And that's how to use SVG icons in Vue.js. If you have any questions feel free to drop them in a comment below. ✌🏽