Skip to content
SvgJsx
Language: English

Convert SVG to a Vue Single-File Component

Wrap any SVG in a Vue 3 single-file component (.vue) with a clean <template>, optional <script setup lang="ts"> and a size prop, ready to import into your app.

Quick presets:
Drop .svg files here orFiles are read locally with FileReader and are never uploaded.
Options
Export:
<script setup lang="ts">
defineOptions({ name: "HeartIcon" });
</script>

<template>
  <svg width="24" height="24" viewBox="0 0 24 24" class="icon icon-heart">
    <g id="Layer_1" fill="none" stroke="#e11d48" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
      <path d="M19.0001 14.0002c1.4900-1.4600 3.0000-3.2100 3.0000-5.5000A5.5000 5.5000 0 0 0 16.5000 3c-1.7600 0-3.0000.5000-4.5000 2-1.5000-1.5000-2.7400-2-4.5000-2A5.5000 5.5000 0 0 0 2 8.5000c0 2.3000 1.5000 4.0500 3 5.5000l7 7Z" style="fill-opacity:0.15;fill:#e11d48" />
    </g>
  </svg>
</template>

Preview

Preview of the converted SVG
Original SVG
706B
Optimized SVG
538B(-24%)
Component
580B

What the Vue output looks like

Vue templates accept SVG attributes as they are, so the converter keeps kebab-case names such as stroke-width and class. It removes editor noise, the XML declaration and optionally xmlns, then places the markup inside a <template> block.

When the size option is enabled, a <script setup> block declares a size prop with a default value and binds it to :width and :height. With TypeScript the prop is declared with defineProps<{ size?: number | string }>() and withDefaults.

Attribute fallthrough

Because the <svg> is the single root element, Vue automatically forwards attributes that are not declared as props. That means class, style, aria-label and event listeners such as @click land on the <svg> without any extra code. The props spread option is therefore not needed for Vue.

Using the component

Typical usage in a Vue 3 or Nuxt project:

  • Save the output as IconName.vue in your components folder.
  • Import it: import IconName from "./IconName.vue".
  • Render <IconName :size="20" class="text-emerald-600" /> in any template.
  • With currentColor enabled the icon follows the CSS color property.

Frequently asked questions

Does the output work with Vue 2?

The template works in Vue 2.7 as well, but <script setup> with defineProps requires Vue 2.7 or Vue 3. For older Vue 2 projects, disable the size prop to get a template-only component.

Can I use it with Nuxt?

Yes. Place the file in the components directory and Nuxt will auto-import it by name, for example <IconArrow /> for components/IconArrow.vue.

Why does Vue warn about <style> inside my SVG?

Vue strips <style> tags from templates because they have side effects. Move the CSS into the component's <style scoped> block or convert it to attributes before converting.

Is vite-svg-loader a better option?

A loader is convenient when you import many SVGs at build time. Converting to .vue files gives you full control over the markup and props and needs no build configuration.