What is the process of importing an SVG file into Vue 3?

I attempted to follow this GitHub repository: https://github.com/visualfanatic/vue-svg-loader/tree/master

Unfortunately, I encountered a version conflict with vue-template-compiler as it is designed for Vue 2.

Next, I tried to use just the main repository: https://github.com/visualfanatic/vue-svg-loader

However, I am encountering an issue with a specific Vue dependency that seems to be missing.

Upon further investigation, I realized there is a complication when using TypeScript where you need to declare a type definition file. Even after adding these declarations, I am still receiving the error "Cannot find module '../../assets/myLogo.svg' or its corresponding type declarations."

Below are the modifications I made:

vue.config.js

module.exports = {
  chainWebpack: (config) => 
  {
    const svgRule = config.module.rule('svg');

    svgRule.uses.clear();

    svgRule
      .use('vue-loader-v16')
      .loader('vue-loader-v16')
      .end()
      .use('vue-svg-loader')
      .loader('vue-svg-loader');
  },
  configureWebpack: process.env.NODE_ENV === 'production' ? {} : {
    devtool: 'source-map'
  },
  publicPath: process.env.NODE_ENV === 'production' ?
    '/PersonalWebsite/' : '/'
}

shims-svg.d.ts

declare module '*.svg' {
  const content: any;
  export default content;
}

MyComponent.vue

<template>
  <div>
     <MyLogo />
  </div>
</template>

<script lang="ts">
import * as MyLogo from "../../assets/myLogo.svg";

export default defineComponent({
  name: "MyComponent",
  components: {
    MyLogo
  },
  props: {
    
  },
  setup(props)
  {
    return {
      props
    };
  }
});


</script>

Answer №1

Vue CLI has built-in support for SVGs without the need for any third-party libraries. It utilizes file-loader internally. To confirm this, simply run the command below in your terminal:

vue inspect --rules

If you see "svg" listed in the output (which you should), then you can easily include SVG files in your Vue components like so:

<template>
  <div>
    <img :src="myLogoSrc" alt="my-logo" />
  </div>
</template>

<script lang="ts">
  // Use `@` as a shorthand for the "src" directory of the project
  import myLogoSrc from "@/assets/myLogo.svg";

  export default defineComponent({
    name: "MyComponent",

    setup() {
      return {
        myLogoSrc
      };
    }
  });
</script>

Therefore, if your goal is solely to display SVGs, you do not require any additional tools or plugins.

Additionally, to meet TypeScript's type declaration requirements, you can add the following code snippet:

declare module '*.svg' {
  // The image file path is essentially a string
  const filePath: string;

  export default filePath;
}

Answer №2

vue-svg-loader does not work with vue 3. To incorporate svg and utilize it as a component, enclose the file contents in 'template'

Usage within component:

<template>
  <div class="title">
    <span>Lorem ipsum</span>
    <Icon />
  </div>
</template>

<script>
import Icon from '~/common/icons/icon.svg';

export default {
  name: 'PageTitle',
  components: { Icon },
};
</script>

Webpack configuration:

{
   test: /\.svg$/,
   use: ['vue-loader', path.resolve(__dirname, 'scripts/svg-to-vue.js')],
}

Content of scripts/svg-to-vue.js:

module.exports = function (source) {
  return `<template>\n${source}\n</template>`;
};

Answer №3

If you're looking to render SVG with all its features, relying solely on an IMG tag might not be the best choice. Check out this comprehensive tutorial for more insights: https://blog.logrocket.com/using-svg-and-vue-js-a-complete-guide/ (specifically point 3)

Your ideal approach for customized SVGs is to create them as Vue Components and then import these components. This method offers a high degree of control over stroke, fill properties, and even allows for dynamic changes by passing Vue variables. Example 3 on the tutorial site demonstrates this concept effectively.

A significant advantage I discovered was the ability to apply CSS color properties directly to the SVG element and have it recognized accurately using the stroke="currentColor" attribute. With an img tag, this modification wouldn't be reflected, resulting in a default black SVG appearance.

Here's an example from my experience where I needed a specific Tabler icon not available in the Tabler Vue 3 library I had imported:

<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-alert-circle-filled" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
  <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
  <path d="M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-4.99 11.66l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -8a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z" stroke-width="0" fill="currentColor" />
</svg>

I proceeded to create a Vue component that served as a wrapper for this SVG:

<template>
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-alert-circle-filled" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
  <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
  <path d="M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-4.99 11.66l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -8a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z" stroke-width="0" fill="currentColor" />
</svg>
</template>

<script>
export default {
   name: 'AlertCircleFilled',
}
</script>

<style scoped>
.icon-tabler-alert-circle-filled {
    /* Add scoped CSS rules here */
}
</style>

To complete the process, I imported and utilized the Vue component, successfully applying my desired CSS color to the SVG:

import AlertCircleFilledIcon from './AlertCircleFilled.vue';
...
components: {AlertCircleFilledIcon, ... },
...
<AlertCircleFilledIcon class="btnIcon" style="color:blue;"/>

Answer №4

Not entirely certain as I haven't tested it with TypeScript, but according to the information provided here

it should be functional.

declare module '*.svg' {
    import type { DefineComponent } from 'vue';
    const component: DefineComponent;
    export default component;
}

I noticed you are using:

import * as MyLogo from "../../assets/myLogo.svg";

I believe it should actually be:

import MyLogo from "../../assets/myLogo.svg";

Answer №5

Here is an example showcasing the use of a freshly installed vue.js 3.2:

<img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125"/>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering an issue with Vue's v-for directive when using a

Having issues using a local filter with v-for and encountering an error Error message: Property or method "filterByTitle" is not defined on the instance but referenced during render. Ensure that this property is reactive, either in the data option, ...

The compile error "Invalid regular expression" occurs when a regex pattern is not formatted correctly

I found a regex pattern on this website that I want to use in my Angular app. To implement it, I copied the regex and enclosed it with two / characters... websiteRegex = /?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._ ...

Create a JavaScript and jQuery script that will conceal specific div elements when a user clicks on them

Within my navigation div, there exists another div called login. Through the use of JavaScript, I have implemented a functionality that reveals additional divs such as login_name_field, login_pw_field, register_btn, do_login_btn, and hide_login upon clicki ...

Personalizing the text of an item in a v-select interface

Can the item-text be customized for the v-select component? I am interested in customizing each item within the v-select dropdown, similar to this example: :item-text="item.name - item.description" ...

Invoking a function in JavaScript from within the same file

Currently in the process of developing a React application. One of the files I am working with is user.utils.js, where I have stored some utility functions that are utilized within my reducer. export const addUser = (state) => {} export const resetUse ...

Is there a way to open a particular Bootstrap tab within a modal using a URL?

I am seeking a way to automatically open a specific tab within a modal using its URL. To achieve this, I have included the following JavaScript code at the end of my website. By entering website.com/#modal-6 in the browser, it will open with modal-6 activa ...

Removing and Cloning Elements with jQuery

segment, here is the unique HTML code I have: exam 456<br> test <span class="highlight" id="2" onclick="test2(this);">shez <ul class="spellcheck_recommend"> <li data-wordid="2" onclick="test(this);">shedding</li& ...

Having trouble setting a background image for a specific DIV element in HTML

I am in the process of updating my webpage, and need some assistance implementing a small background image. Here is what I have done so far: https://i.sstatic.net/nTxtD.png Below is the marked section where I am trying to add the background image: https ...

Using NgTable to sort and filter selections

I am working with two select elements. The first select is populated with names, and I would like the second select to only display the ages corresponding to the selected name. For example: If I select Jacob in the first select, I want the Age select to ...

What is the correct way to change the v-model value of a child component within a parent component

Currently, I am in the process of mastering Vue.js and I have a specific goal. I want to modify the binding value of the child component's v-model and then trigger an event in the parent component. As I delve into the Element UI documentation, I aim ...

Alter the font color of text using JavaScript in an HTML document

I am struggling to change the title color in my HTML code below, but the text color does not seem to be changing. How can I make this adjustment? /** * Generate a HTML table with the provided data */ Highcharts.Chart.prototype.generateTable ...

Unable to set an onclick function within a customized dojo widget

I have a custom widget that I've defined as shown below: dojo.declare('myWidget', [dijit._WidgetBase, dijit._Templated], { 'templateString':'<span>' + '<a dojoAttachPoint="linkNode" href="b ...

Tips for providing all props to a React component while still including necessary props specified in an interface

Am I overlooking something or is this a different issue altogether? import * as React from 'react'; interface Props { value: string; } const MyComponent = (props: Props) => { const { value, ...rest } = props; return ( & ...

Error: The function req.logIn is not recognized - Passport JS

After researching extensively, I am confident that the issue I'm facing is not a known bug. I am currently utilizing passport JS with the local strategy in my login route, employing a custom callback and invoking req.login once I confirm the user&apos ...

The combination of the video tag within an SVG element is causing a strange error

I'm encountering an issue while attempting to implement the code provided in this particular answer. Despite following the code, I am receiving an error in the console log instead: Here's the Code Snippet: <svg version="1.1" class="center-bl ...

Utilizing JavaScript to incorporate Angular attributes into child nodes

I just found this code snippet: <div id="colors"> <div id="red" >Red</div> <div id="green" >Green</div> <div id="blue" >Blue</div> <div id="purple" >Purple</div> <div id="gray" & ...

In need of secure HTML, received a dose of Style instead

I am currently developing a component that loads html content dynamically and validates the loaded styles to prevent any mixing of app styles with the dynamic template's styles. This is the structure of my HTML component: <div class="modal-header ...

Float over a specific line in a drawing

I am looking to develop a unique rating system using css, html, and potentially js : https://i.sstatic.net/pQP79.png My goal is for the user to hover over a specific section of a circular stroke and have it fill with a particular color, all while maintai ...

"The click event doesn't seem to be functioning properly on HTML content loaded dynamically through JavaScript

I have set up a dynamic page that initially loads 10 elements. As the user scrolls down, I use JavaScript to append more elements to the page via AJAX. Additionally, when a tag is clicked, some JavaScript functionality is triggered. Specifically, I am uti ...

Storing combined data as an object within a single field in Laravel's store functionality

Currently, I am facing a challenge in storing repeater data into the database using Laravel. To achieve this, I need to merge some data with varying values. The structure of my form is as follows: <div v-for="(tab, tabIndex) in tabs" :key=&qu ...