SVG and Vue.js — A 2 Minute Love Story
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
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?