SVGFlow
Open editor

SVG to Vue component

Convert SVG to a Vue single-file component. Vue templates take SVG attributes exactly as written, and with a single root element every attribute the parent passes falls through to the <svg> — no spread needed.

Runs entirely in your browser — nothing is uploaded, no account needed.

Previewno file
Drop an SVG to convert
Or paste markup below · max 2 MB
Component
Open an SVG to see the component.
Component name
FileIcon.vue

How to convert SVG to a Vue component

Drop an SVG file or paste its markup, name the component, and copy or download the .vue file. The conversion runs entirely in your browser — the file is parsed, pretty-printed with two-space indents, and placed inside a <template> block; nothing is sent anywhere. The <script> block that follows exports only a name: export default { name: 'IconName' }, derived from the file name unless you type one. That is the entire component, and the brevity is the point — in Vue, an SVG icon needs almost no wrapping at all.

Unlike the JSX converter, no attribute is renamed. Vue templates are parsed as templates, not compiled to property access, so stroke-width, fill-rule and stop-color are valid exactly as the file wrote them. What you see in the output is what the file contained, indentation aside — which also means diffs against the source SVG stay readable when the icon is updated later.

Fallthrough attributes do the work of props

The component declares no props, and does not need to. When a Vue component has a single root element, every attribute the parent passes that the component does not declare falls through to that root automatically. Write <IconName width="16" height="16" /> and both attributes land on the <svg>; the same goes for fill, aria-label, and v-on listeners like @click. For most attributes the parent's value replaces the template's; class and style are the exception — Vue merges them, so a class baked into the file and a class from the caller both apply. That merge is something the React spread cannot do, and it is worth knowing you have it.

The mechanism has edges. It requires the single root — wrap the svg in a div and fallthrough targets the div; add a sibling, even a comment, and Vue no longer knows where to send the attributes. And a component that wants to intercept a value — say, map a size prop onto both width and height — must declare it as a prop, at which point it stops falling through. The fallthrough guide works through these cases, including inheritAttrs: false with an explicit v-bind="$attrs" when you need control over placement.

Registering and theming the icon

The emitted options object works in Vue 3 and Vue 2.7, with <script setup> parents or Options API parents alike — the component itself has no reactivity to declare. Import it locally where it is used, or register a directory of icons globally in a plugin if the set is small. For colour, the pattern is the same as every framework, but Vue's version is tidy: convert hard-coded fills to currentColor with the Color Replacer before converting, then style the component with the CSS color property — or lean on fallthrough and pass fill directly from the parent for one-off recolours. Scoped styles in the parent do not reach into the child's template, so currentColor plus inherited color is the mechanism that actually crosses the boundary.

Vue 2, v-html, and what this replaces

A common Vue habit is injecting icon strings with v-html. It works until it doesn't: the compiler cannot check the markup, the strings dodge the build's template compilation, and every injection site is an XSS review. A single-file component gives the compiler the markup, gives you fallthrough, and costs one small file. The output here targets Vue 3 and Vue 2.7; for older Vue 2, the only change needed is moving the name into whatever options object your setup already uses. If the icon arrives as designer-exported markup, run it through the Optimizer first — template bytes are compiled into render-function bytes, and the cruft comes along if you let it.

Common problems

  • Fallthrough stopped working. The template no longer has a single root — a wrapper element or a stray sibling comment turns automatic fallthrough off. Keep the template as emitted, or bind $attrs explicitly.
  • Two instances restyle each other. Gradient and clip-path ids are global to the page, exactly as in the React version of this problem. Suffix ids per instance if an icon appears twice with different fills.
  • The icon ignores your CSS color. Hard-coded fills beat inheritance. Convert fills to currentColor and style with color; scoped styles on the parent cannot reach the paths directly.
  • An attribute you passed did not replace the file's. If it was class or style, it merged instead — that is fallthrough behaving as designed. Edit the file's own class out if you want the caller's alone.

When not to make components

A component per icon suits the icons an app renders constantly. For a large occasional set, every SFC is a module in the bundle; an SVG sprite referenced by fragment keeps one cacheable document and no JavaScript per icon, and works in server-rendered Vue as well. Purely decorative shapes are often better as CSS data URIs, with no template involvement at all. The dividing line is interactivity and theming: anything that needs props, events or currentColor earns componenthood; anything static mostly doesn't.

Questions

Is this SVG to Vue converter free?

Yes — free, with no account, no watermark and no limit on conversions. The site is funded by advertising.

Does my SVG leave my browser?

No. Parsing and formatting happen locally in the page; there is no server involved and nothing to upload to.

Which Vue versions does the output support?

Vue 3 and Vue 2.7 as emitted. For older Vue 2, move the name into the options object your project already uses — the template itself is version-agnostic.

Why are the SVG attributes not renamed to camelCase?

Because Vue templates accept them as written. Kebab-case attributes like stroke-width are only a problem in JSX, where attributes compile to JavaScript property names. Vue compiles templates itself and handles SVG natively, so the markup stays untouched and diffable against the source file.

How do I set the size of the icon?

Pass width and height where you use it: <IconName width="16" height="16" />. With a single root element, undeclared attributes fall through to the <svg> automatically — no props needed. Setting size in CSS on the component works too.

How do I change the icon’s colour?

Convert its fills to currentColor first — the Color Replacer does it in one click — then set the CSS color property on the component or any ancestor. Alternatively pass fill="…" directly; it falls through to the root svg and replaces the template's value.

Do click handlers work without declaring emits?

Yes. v-on listeners are part of fallthrough: @click on the component becomes a native click listener on the root <svg>. Nothing needs declaring for the plain case.

Why did the class I passed not replace the one in the file?

Vue merges class and style during fallthrough instead of replacing them — both classes end up on the element. Every other attribute is replaced by the parent’s value. If you want only the caller’s class, remove the one inside the template.

Does it work with <script setup>?

Yes. The component uses a plain options export, which any Vue 3 project consumes regardless of how the parent components are written. There is no state inside an icon to need script setup for.

Can I use the converted component with Nuxt?

Yes. It is a standard single-file component; drop it in components/ and Nuxt auto-imports it. It renders fine on the server since it contains no browser-only code.

Are comments in the SVG preserved?

Yes. The formatter keeps XML comments, so licence headers and editor notes survive into the template. Strip them with the Optimizer beforehand if you would rather ship without them.

Notes

  • Kebab-case attributes are valid in Vue templates, so the markup is not rewritten — what you see is what the file contained.
  • Fallthrough covers class, style, width, events — everything. Add explicit props only when you want to intercept a value.
  • Works in Vue 3 and Vue 2.7. For older Vue 2, move the name into the options object you already have.

Related tools