lobo_tuerto's notes

Fluid SVGs with Vue 3

Have your SVGs adjust to their parents width.

📅Published09 March 2018Last updatedAug 2022
demofrontendsvgvue 3

Interactive demo

This is a fluid SVG. Check it out, move the slider.

Current parent div width: 50%

Here, if the div grows the svg will also grow.
This is very convenient as we get resize adaptability for free.

Fluid SVGs

A fluid SVG is one that can grow as far as its parent allows it to.
The trick lies in how we define the <svg> element.

We should only set the viewBox attribute, and don’t set a height nor width on it.
It’ll preserve its aspect ratio, growing and shrinking accordingly.

This is the svg component src/components/svg/SvgBox.vue:

  <svg viewBox="0 0 1000 1000" class="bg-stone-300">
      class="fill-amber-600 stroke-black stroke-2"

This is the container src/components/svg/SvgWrapper.vue:

<script lang="ts" setup>
import { computed } from 'vue'

const props = defineProps<{
  width: string

const widthPercent = computed(() => `${props.width}%`)

  <div class="svg-wrapper">

<style scoped>
.svg-wrapper {
  width: v-bind('widthPercent');

It just contains a <div> with a configurable width — that’s how the slider controls it.
The SvgBox will shrink and grow as much as permitted by the wrapper’s width.

The code for the mini-demo above is just this:

<script setup lang="ts">
import { ref } from 'vue'

import SvgBox from '@/components/svg/SvgBox.vue'
import SvgWrapper from '@/components/svg/SvgWrapper.vue'

const width = ref('50')

  <div>Current parent <strong>div</strong> width: {{ width }}%</div>

  <input v-model="width" type="range" />

  <SvgWrapper :width="width">

That’s it! 😁

Got comments or feedback?
Follow me on