Reputation: 944
In vue single file component. I import a svg file like this:
import A from 'a.svg'
And then how can I use A
in my component?
Upvotes: 81
Views: 179113
Reputation: 9344
My favourite approach is to create an SVG Vue component and then use it wherever I need it.
The good thing about this is that you can add encapsulated custom styles, pass props or have custom logic (e.g. animation, badges, etc) to fit your needs.
Example
<template>
<svg
class="custom"
width="314"
height="318"
viewBox="0 0 252 213"
fill="none"
xmlns="http://www.w3.org/2000/svg"
<path id="somePath" ... />
</svg>
</template>
<style scoped>
.custom {
-webkit-transform: translate(-30px, -20px);
transform: translate(-30px, -20px);
}
</style>
Import it anywhere in the Vue app
<script setup lang="ts">
import MySvg from "@/components/MySvg.vue"
</script>
<template>
<div>
<MySvg />
</div>
</template>
Upvotes: 0
Reputation: 3665
If you're using Vite (which most of you should), then you can append ?raw
at the end of your import.
import arrowLeftIcon from '@/assets/svg/arrow-left.svg?raw'
This will return the raw svg string and you can render it as an html using v-html
:
<div v-html="arrowLeftIcon" class="w-4 h-4" />
Upvotes: 1
Reputation: 1594
For anyone using Vite and not Webpack: Solution 2 from this article worked great for me with Vue 3 inside Astro.
vite-svg-loader
.import svgLoader from 'vite-svg-loader';
export default defineConfig({
plugins: [
// ...
svgLoader(),
],
});
or for Astro:
import { defineConfig } from 'astro/config';
import vue from '@astrojs/vue';
import svgLoader from 'vite-svg-loader';
// https://astro.build/config
export default defineConfig({
integrations: [
vue(),
],
vite: {
plugins: [vue(), svgLoader()],
},
});
<script setup>
import { defineAsyncComponent } from 'vue';
const props = defineProps({
name: {
type: String,
required: true,
},
});
const icon = defineAsyncComponent(() => import(`./icons/${props.name}.svg`));
</script>
<template>
<component :is="icon" />
</template>
<template>
<Icon name="foobar" />
</template>
<script>
import Icon from './Icon.vue';
export default {
components: {
Icon,
},
}
</script>
Upvotes: 3
Reputation: 122
I was able to get svgs loading inline via
<div v-html="svgStringHere"></div>
Where svgStringHere
is a computed property that returns an svg as a string
Upvotes: 0
Reputation: 556
You can also use something like this:
<template>
<img :src="logo"></img>
</template>
<script>
import logo from '../assets/img/logo.svg'
export default {
data() {
return {
logo
}
}
}
</script>
This doesn't require installing external modules and works out of the box.
Upvotes: 9
Reputation: 491
+1 for @Stephan-v's solution, but here's a slightly modified approach for 2021 with Webpack 5.
<template/>
Option A: Single SVG file
<template>
<svg viewBox="0 0 24 24">
<use :xlink:href="require('@/assets/icons/icon.svg')"></use>
</svg>
</template>
Option B: SVG Sprite (e.g. for FeatherIcons)
<template>
<svg viewBox="0 0 24 24">
<use
:xlink:href="require('@/assets/icons/sprite.svg') + `#${iconName}`"
></use>
</svg>
</template>
<script>
export default {
props: {
// Dynamic property to easily switch out the SVG which will be used
iconName: {
type: String,
default: "star",
},
},
};
</script>
NOTE: You may not need the Webpack Loader if you're using Vue 3 (as mentioned above) or Vite. If you're using Storybook or Nuxt, you will likely still need it.
$ npm install svgo-loader -D
$ yarn add svgo-loader -D
webpack.config.js
(or similar)
module.exports = {
mode: "development",
entry: "./foo.js",
output: {},
// ... other config ...
module: {
rules: [
/////////////
{
// Webpack 5 SVG loader
// https://webpack.js.org/guides/asset-modules/
// https://dev.to/smelukov/webpack-5-asset-modules-2o3h
test: /\.svg$/,
type: "asset",
use: "svgo-loader",
},
],
/////////////
},
};
Upvotes: 0
Reputation: 751
I like to use pug as a template engine (comes with many advantages) - if you do so, you will be able to easily include files like SVG's just by writing:
include ../assets/some-icon.svg
That's it! there is nothing else to do - I think this is an very easy and convenient way to include stuff like smaller svg's - file's easily included code is still clean!
Here you can get some more information how to include PugJS into you Vue instance https://www.npmjs.com/package/vue-cli-plugin-pug
Upvotes: 3
Reputation: 22147
I would just use vue-svg
Install via Vue CLI 3:
vue add svg
Input:
<img src="@/assets/logo.svg?data" />
Output:
<img src="data:image/svg+xml;base64,..." />
or this is work also...
import LogoImage from "@/assets/logo.svg?inline"
Upvotes: 8
Reputation: 2391
I've gotten the following to work in Vue 3. Doesn't require messing with webpack or installing any third party plugins.
<template>
<img :src="mySVG" />
</template>
<script>
export default {
name: 'App',
data(){
return {
mySVG: require('./assets/my-svg-file.svg')
}
}
}
</script>
Note: I'm aware that you cannot modify certain pieces of the SVG when using it in img src, but if you simply want to use SVG files like you would any other image, this seems to be a quick and easy solution.
Upvotes: 49
Reputation: 19
First you need a specific loader for the component which will contain the svg my webpack.base.config.js
module: {
rules: [
{
test: /\.svg$/,
loader: 'vue-svg-loader',
},
{
test: /\.vue$/,
use: [
{
loader: "vue-loader",
options: vueLoaderConfig
},
{
loader: "vue-svg-inline-loader",
options: { /* ... */ }
}
]
}
//.. your other rules
}
docs of vues-svg-inline-loader : https://www.npmjs.com/package/vue-svg-inline-loader
docs of vue-svg-loader : https://www.npmjs.com/package/vue-svg-loader
Next, you can initialise a vue file
<template>
<div>
<img svg-inline class="icon" src='../pathtoyourfile/yoursvgfile.svg' alt="example" />
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'logo',
data () {
},
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#logo{
width:20%;
}
.rounded-card{
border-radius:15px;
}
//the style of your svg
//look for it in your svg file ..
//example
.cls-1,.cls-7{isolation:isolate;}.cls-2{fill:url(#linear-gradient);}.cls-3{fill:url(#linear-gradient-2);};stroke-width:2px;}..cls-6{opacity:0.75;mix-blend-mode:multiply;}.cls-7{opacity:0.13;}.cls-8{fill:#ed6a29;}.cls-9{fill:#e2522b;}.cls-10{fill:#ed956e;}.cls-185{fill:#ffc933;}..cls-13{fill:#ffd56e;}.cls-14{fill:#1db4d8;}.cls-15{fill:#0f9fb7;}.cls-16{fill:#3ad4ed;}.cls-17{fill:#25bdde;}.cls-18{fill:#fff;}
//
</style>
Your svg fils must dont contain style tag so copy paste the style in the vue style with scoped propoerty to keep it specific to this component
you can just load you component in specific place of your app
and use it
<template>
<v-app id="app">
<logo/>
<router-view/>
</v-app>
</template>
<script>
import logo from './components/logo.vue'
export default {
name: 'App',
data(){
return {
//your data
}
},
components:{
logo //the name of the component you imported
},
}
}
</script>
<style>
#app {
font-family: 'Hellow', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #070b0f;
margin-top: 60px;
}
</style>
Upvotes: 2
Reputation: 20289
If you are using Webpack you can use the require context to load SVG files from a directory. Be aware that this will put all SVG files within your Javascript files and might bloat your code though.
As a simplified example I am using this svg
component:
data() {
return {
svg: ''
};
},
props: {
name: {
type: String,
required: true
}
}
created() {
this.svg = require(`resources/assets/images/svg/${this.name}.svg`);
}
The template simply looks like this:
<template>
<div :class="classes" v-html="svg"></div>
</template>
Normally you can't simply load SVG files like that and expect them to be used with a v-html
directive since you are not getting the raw output. You have to use the Webpack raw-loader
so make sure you get the raw output:
{
test: /\.svg$/,
use: [
{
loader: 'raw-loader',
query: {
name: 'images/svg/[name].[ext]'
}
},
{
loader: 'svgo-loader',
options: svgoConfig
}
]
}
The example above also uses the svgo-loader
since you will want to heavily optimize your SVG files if you do down this route.
Hopefully this help you or anyone else out on how to solve this without diving straight into a third-party solution to fix this.
Upvotes: 12
Reputation: 760
You can always save it as a .svg file in your /static/svg/myfile.svg
(using webpack) and just use it as an image file: <img src="/static/svg/myfile.svg">
. No require / import / loader needed.
Upvotes: 0
Reputation: 1748
If you have control over the svg file, you can just wrap it in a vue file like so:
a.vue:
<template>
<svg>...</svg>
</template>
Just require the file like this afterwards: import A from 'a.vue'
Upvotes: 38
Reputation: 649
Based on the information you provided, what you can do is:
npm install --save-dev vue-svg-loader
module: {
rules: [
{
test: /\.svg$/,
loader: 'vue-svg-loader', // `vue-svg` for webpack 1.x
},
],
},
<template>
<nav id="menu">
<a href="...">
<SomeIcon class="icon" />
Some page
</a>
</nav>
</template>
<script>
import SomeIcon from './assets/some-icon.svg';
export default {
name: 'menu',
components: {
SomeIcon,
},
};
</script>
Reference: https://github.com/visualfanatic/vue-svg-loader
Upvotes: 57