How To Add Custom SVG Icon in Vuetify - Vue
Asked Answered
O

6

32

I'm using vuetify 1.1.8 and vue 3.0.0-rc.3. I am trying to use some of the custom SVG icons in my project, which I have designed, instead of default icons from Material Icons or FontAwesome Icons which are supported by vuetify

I have tried using vue-svg-loader to load my custom svg icons, and use them as components. Something like this

<template>
    <icon-one></icon-one>
</template>

<script>
    import iconOne from './public/iconOne.svg'
    export default{
        components:{
                 iconOne
          }
    }
</script>

But the problem with vue-svg-loader is that I cannot use them in <v-text-field>'s append-icon and many other places where I had freedom with <v-icon>.

I have also read the vuetify docs where they have mentioned about using custom icons but I don't think that is helping too.

Can someone help me out with this. May be I should try sprite-images as supported by material angular

TL;DR

I have custom self-made SVG Icons, and I want to use them as <v-icon>customIcon</v-icon> in vuetify

Obeded answered 31/7, 2018 at 13:27 Comment(2)
What's stopping you just using the standard image tag and sizing appropriately using css? or wrapping this in a component for reuse manually, it shouldn't really change much overall and isn't much hassle.Chariness
img tags suck. Especially if you want the icon the same size as the font size to the left or right side of the icon. Like when you want to use the icon like a span tag.Evanesce
C
48

Per vuetify v2 docs

Create custom component which contains the svg icon code

// CustomIcon.vue
<template>
  <svg>
    ...
  </svg>
</template>

Include the custom icon component in vuetify config:

// vuetify.ts

import CustomIcon from '@/components/CustomIcon.vue'

export default new Vuetify({
  theme: {/**/},
  icons: {
    values: {
      custom: { // name of our custom icon
        component: CustomIcon, // our custom component
      },
    },
  },
})

Use it like so

<v-icon>$vuetify.icons.custom</v-icon>

Or shortcut:

<v-icon>$custom</v-icon>

Coltish answered 25/10, 2019 at 18:32 Comment(5)
@GeorgeAlvis So this solution worked for me in Nuxt: codesandbox.io/s/z42mm?file=/pages/index.vue Basically you have to move some Vuetify options into a file you import via the Vuetify optionsPath so that you can import Vue icon components into that Vuetify options file.Newburg
i tried this but for whatever reason nothing appears and no errors are shown.Kolosick
@Otorrinolaringologista-man hm, maybe faulty SVG? Happened to me... No other ideas except maybe make sure there are no typos, and make sure you structured it properly.Coltish
This doesn't appear to be working anymore. My local attempt is getting the same error displayed on the sandbox posted by @NewburgStrove
Doesn't work for me either.Colliery
K
24

You can, indeed, create a vue icon inside of its own Vue single file component, and then register this component so that vuetify can use it inside of the VICon (v-icon) component.

To create a vue component icon, you just need to place an SVG inside of the template tags as shown in the Vue Cookbook. This document should help you use the component in any vue app, as well.

<template>
    <svg>...</svg>
</template>

Next, you need to register this component with vuetify. The Vuetify config is sometimes in the index file, or in the modern vue-cli, it will be found in @/src/plugins/vuetify.js.

There, you can register your component as shown on Vuetify's site (you already mentioned this link), but maybe this documentation is an update or unclear.

Now this component will be registered and can be used anywhere inside of VApp. However, unlike standard icons, you need to use $vuetify.icons.[icon-name] inside the slot of v-icon. In the Vuetify example, the icon is registered as 'product.' To use this, you'd include

<v-icon>$vuetify.icons.product</v-icon>

I have this working in an on-going project. I'll leave a branch of the current state here.

The icon component is in /src/icons. The Vuetify config is in /src/plugins, and svg icon component is in /src/components/PlotSelector.vue.

Kent answered 26/4, 2019 at 23:45 Comment(0)
H
4

Dependencies:

  • vue: "^3.x"
  • vuetify: "^3.x"
  • vite: "^4.x"

  1. Add Vite SVG Loader
npm i -D vite-svg-loader
  1. Add aliases to Vuetify config
// plugins/vuetify.ts

import settings from '@/assets/icons/settings.svg'; // <- custom icon

import { IconAliases, createVuetify } from 'vuetify';
import { aliases as defaultAliases } from 'vuetify/iconsets/mdi';

const aliases: IconAliases = {
  ...defaultAliases,
  settings,
};

export default createVuetify({
  icons: {
    aliases,
  },
});
  1. Use in your template by icon name with $ prefix
<v-btn icon="$settings"></v-btn>
Harding answered 17/7, 2023 at 15:43 Comment(3)
It's worth mentioning that you need to add vite-svg-loader to vite's config plugins: npmjs.com/package/vite-svg-loader#setupPrecognition
Uncaught (in promise) Error: Could not find aliased icon "$settings"Shackle
@ShadowGames, could you please provide more details (a playground) to reproduce your issue?Harding
H
2

My final solution for Nuxt, but you can adopt it to pure vuejs:

npm i '@nuxtjs/svg' -D

nuxt.config.js:

buildModules: [
  '@nuxtjs/svg'
],
vuetify: {
  customVariables: ['~/assets/variables.scss'],
  treeShake: true,
  optionsPath: './vuetify.config.js'
},

vuetify.config.js

icons: {
  iconfont: 'mdi',
  values: {
    chat: {
      component: require('~/assets/img/icons/chat.svg?inline')
    }
  }
}

chat.svg (don't forget to set: fill="currentColor")

<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M16.5569 3H3.44278C2.09549 3 1 4.09596 1 5.44313V13.1331C1 14.4802 2.09549 15.5762 3.44278 15.5762H13.3415L15.4019 18.0107C15.4723 18.0944 15.5757 18.1402 15.6816 18.1402C15.7238 18.1402 15.766 18.1323 15.8075 18.1173C15.952 18.0643 16.0478 17.927 16.0478 17.7739V15.5761H16.5572C17.9043 15.5761 19 14.4802 19 13.133V5.44313C18.9997 4.09596 17.9044 3 16.5569 3ZM7.18042 10.2514C6.7072 10.2514 6.32357 9.86785 6.32357 9.39499C6.32357 8.92141 6.7072 8.53796 7.18042 8.53796C7.65328 8.53796 8.03709 8.92141 8.03709 9.39499C8.03709 9.86791 7.65328 10.2514 7.18042 10.2514ZM9.99967 10.2514C9.52645 10.2514 9.143 9.86785 9.143 9.39499C9.143 8.92141 9.52645 8.53796 9.99967 8.53796C10.4725 8.53796 10.8562 8.92141 10.8562 9.39499C10.8562 9.86791 10.4725 10.2514 9.99967 10.2514ZM12.9953 10.2514C12.522 10.2514 12.1382 9.86785 12.1382 9.39499C12.1382 8.92141 12.522 8.53796 12.9953 8.53796C13.4681 8.53796 13.852 8.92141 13.852 9.39499C13.852 9.86791 13.4681 10.2514 12.9953 10.2514Z" fill="currentColor"/>
</svg>

Any component:

<v-icon>$chat</v-icon>

Hope, this helps you guys.

Haarlem answered 30/9, 2021 at 14:58 Comment(1)
This seems to override the theme. Background suddendly whiteWayside
D
1

For Vuetify & Nuxt, you can do it this way:

Put your logo file into static folder and create your CompanyLogo.vue inside components folder:

<template>
  <img src="/company-logo.svg">
</template>

Then you can use it in every other component via <CompanyLogo />

You could also animate it if you wanted to, e.g. like this:

<template>
  <img
    class="LogoAnimation"
    src="/company-logo.svg"
  >
</template>

<style>
.LogoAnimation {
  transform: rotateY(560deg);
  animation: turn 3.5s ease-out forwards 1s;
}

@keyframes turn {
  100% {
    transform: rotateY(0deg);
  }
}
</style>
Duumvir answered 18/8, 2020 at 14:12 Comment(1)
The OP was asking specifically about <v-icon>s, not just displaying an svgDorris
G
1

You can also create a CSS class that uses a mask to apply the SVG graphics.

For instance, in my implementation, I have the class in global.css which is imported in main.ts meaning is available throughout the app.

.some-icon {
  background-color: #f69e01;
  -webkit-mask: url(@/assets/someLogo.svg) no-repeat center;
  mask: url(@/assets/someLogo.svg) no-repeat center;
}

And then, in any template, it can be used by adding the custom class to the <v-icon> element:

<v-icon class="some-icon" />
Gorky answered 19/8, 2023 at 8:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.