Managing SVG Icons in VueJs applications

Using the right icons can make our applications not only better looking but also more intuitive. Inline SVG icons are safe, sharp, and easy to customize, but they tend to ruin our markup and make it less pleasant to navigate.

Another problem is that they are hard to re-use. Because, one, you cannot really know which icon is which unless you figure out from the surrounding markup or by refreshing the browser, and two, when you want to change an SVG icon you have to find and replace all the occurrences in your app, which isn’t that nice.

Two solutions solve this problem:

One is to install a vue-svg-loader that will allow you to import SVG files directly and treat them as Vue components.

<template>
  <nav>
    <a href="https://github.com/vuejs/vue">
      <VueLogo />
      Vue
    </a>
    <a href="https://github.com/svg/svgo">
      <SVGOLogo />
      SVGO
    </a>
    <a href="https://github.com/webpack/webpack">
      <WebpackLogo />
      webpack
    </a>
  </nav>
</template>
<script>
import VueLogo from './public/vue.svg';
import SVGOLogo from './public/svgo.svg';
import WebpackLogo from './public/webpack.svg';
 
export default {
  name: 'Example',
  components: {
    VueLogo,
    SVGOLogo,
    WebpackLogo,
  },
};
</script>

The downside is that you have to import each individual icon, and you end up with somewhat imprecise names. Having an inbox.svg icon and using it as an <inbox /> component would be confusing. Yes, you might solve that with an icon prefix or suffix, but still, I think the next solution is better.

The second option, and the one I personally like to use in my projects, is to create a single Icon component that holds all the svgs and shows the correct one based on a name prop I pass in. The component looks something like this:

//Icon.vue
<template>
  <svg v-if="name==='inbox'"...</svg>
  <svg v-else-if="name==='chevron-right'"...</svg>
  <svg v-else-if="name==='chevron-left'"...</svg>
</template>

<script>
  export default {
    props: ['name'],
  }
</script>

Since this component is something I’ll probably use throughout the entire app, I register it as a global component in my app.js.

//app.js
Vue.component('icon', require('./Icon.vue').default);

// usage
<icon name="chevron-right" class="w-6 h-6"/>

Now I can use the icon component wherever I want, and if someday I need to replace one specific icon with another, all I need to do is to update the SVG code in the Icon.vue file, and the icon will change everywhere.

If you’re still somewhat confused, I’ve also made a video on this issue: https://www.youtube.com/watch?v=FTwA-ZnQmCQ

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.