lobo_tuerto's notes
Home
Blog
Notes
About

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:

<template>
  <svg viewBox="0 0 1000 1000" class="bg-stone-300">
    <rect
      x="100"
      y="100"
      width="300"
      height="300"
      class="fill-amber-600 stroke-black stroke-2"
    ></rect>
  </svg>
</template>

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}%`)
</script>

<template>
  <div class="svg-wrapper">
    <slot></slot>
  </div>
</template>

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

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')
</script>

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

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

  <SvgWrapper :width="width">
    <SvgBox></SvgBox>
  </SvgWrapper>
</template>

That’s it! 😁


Got comments or feedback?
Follow me on
v-24390d0