SVG and Vue.js — A 2 Minute Love Story

Rob Yedlin
The Duo
Published in
2 min readApr 22, 2018

At State of the ÐApps, we run our front-end on Nuxt.js. If you haven’t heard of Nuxt, but know and like Vue, I strongly urge you to check it out. It comes with SSR, build commands, tooling, linting, code splitting, routing, state management and much more, right out of the box. It’s scalable, light, performant, and maintainable. We love it.

Our designer Chris is migrating to SVG icons for State of the ÐApps, and I’ve found that implementing them in Vue is dreamy.

Let’s make this work in Vue

Here’s the SVG component

1. Starting with the SVG from Illustrator

<svg width=”45” height=”45” viewBox=”0 0 512 512">
<path class=”dark” d=”M492.3,512.1H19.7C8.8,512.1,0,503.3,0,492.4V19.6C0,8.8,8.8,0,19.7,0h472.6C503.2,0,512,8.8,512,19.6v472.6 C512.1,503.1,503.3,512.1,492.3,512.1z M178.6,366.8c0,11.5–1,15.5–10,15.5h-3c-9.5,0–10.5–4–10.5–15.5v-69.9h-50.4v76.3c0,46.4,11,59.9,53.4,59.9h21c42.4,0,53.4–13.5,53.4–59.9v-44.4c0–45.4–12–62.4–42.9–95.8c-25–26.5–31.4–36–31.4–60.9v-27.9 c0–10.5,1.4–14.5,10.5–14.5h3c8.9,0,10.5,4,10.5,15.5v55.9h50.4v-62.4c0–46.4–11–59.9–53.4–59.9h-21c-42.4,0–53.4,13.5–53.4,59.9 V170c0,45.4,11.5,62.4,42.4,96.4c25,26,31.4,36,31.4,60.4V366.8z M263.7,430.7h90.1c42.4,0,53.4–13.5,53.4–59.9V141.1 c0–46.4–11–59.9–53.4–59.9h-90.1v149.3h-20.2v50.8h20.2V430.7z M317.5,379.7v-98.3H341v-50.8h-23.3v-98.3h25.2 c9.5,0,10.5,4,10.5,15.5v216.6c0,11.5–1,15.5–10.5,15.5H317.5z”/></svg>

2. Now let’s make it a single file component

We’ll write this file to ~/components/SvgLogoIcon.vue, and abstract away any of the variable attributes.

<template>
<svg class="component-SvgIconLogo" :width="size" :height="size" viewBox="0 0 512 512">
<path :class=”theme” d=”M492.3,512.1H19.7C8.8,512.1,0,503.3,0,492.4V19.6C0,8.8,8.8,0,19.7,0h472.6C503.2,0,512,8.8,512,19.6v472.6 C512.1,503.1,503.3,512.1,492.3,512.1z M178.6,366.8c0,11.5–1,15.5–10,15.5h-3c-9.5,0–10.5–4–10.5–15.5v-69.9h-50.4v76.3c0,46.4,11,59.9,53.4,59.9h21c42.4,0,53.4–13.5,53.4–59.9v-44.4c0–45.4–12–62.4–42.9–95.8c-25–26.5–31.4–36–31.4–60.9v-27.9 c0–10.5,1.4–14.5,10.5–14.5h3c8.9,0,10.5,4,10.5,15.5v55.9h50.4v-62.4c0–46.4–11–59.9–53.4–59.9h-21c-42.4,0–53.4,13.5–53.4,59.9 V170c0,45.4,11.5,62.4,42.4,96.4c25,26,31.4,36,31.4,60.4V366.8z M263.7,430.7h90.1c42.4,0,53.4–13.5,53.4–59.9V141.1 c0–46.4–11–59.9–53.4–59.9h-90.1v149.3h-20.2v50.8h20.2V430.7z M317.5,379.7v-98.3H341v-50.8h-23.3v-98.3h25.2 c9.5,0,10.5,4,10.5,15.5v216.6c0,11.5–1,15.5–10.5,15.5H317.5z”/></svg>
</template>
<script>
export default {
props: {
theme: {
default: 'dark',
type: String
},
size: {
default: 45,
type: Number
}
}
}
</script>
<style lang="scss" scoped>
@import '~assets/css/settings';
.dark {
/* #333 */
fill: $color--black;
}
.light {
/* #fafafa */
fill: $color--white;
}
</style>

That’s it! Now we can use this as a Vue component anywhere, with props for theme, width, and height on the SVG (we use one size prop because it’s a square). Notice that we also have off-black and off-white colors stored as variables in an SCSS settings file. Chris assures me that ”black” should never truly be #000.

We’re also using scoped styles so that we restrict it only to the component (and it’s immediate child root elements) and don’t pollute our global css. This is the stuff dreams are made on.

3. Let’s wrap this up by using the component

To keep things simple, here’s a basic example.

<template>
<nuxt-link class="link" :to="{ name: 'home' }">
<SvgLogoIcon theme="light" :size="45" />
</nuxt-link>
</template>
<script>
// assuming our component is already in the same folder
import SvgLogoIcon from './SvgLogoIcon'
export default {
components: {
SvgLogoIcon
}
}

We’ll assign the string dark to the theme prop, and we’ll need to use colon syntax to assign a number to the size prop.

That’s it. Pretty lovely, eh?

--

--