We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
2018 / 03 / 09
2022 / 08 / 02
Fluid SVGs with Vue 3
Have your SVGs adjust to their parents width.
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.
Only set the viewBox attribute, but don’t set a
height nor width on it.
Thus, 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! :grin: