Skip to main content
Vuetify0 is now in alpha!
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

AspectRatio

Reserves a box with a fixed width-to-height ratio using CSS aspect-ratio.

Usage

Wrap any content whose height should track its width. The child fills the reserved frame — pair with w-full h-full or absolute positioning.

16 / 9
<script setup lang="ts">
  import { AspectRatio } from '@vuetify/v0'
  import { shallowRef } from 'vue'

  const ratios = [
    { label: '1 / 1', value: '1 / 1' },
    { label: '4 / 3', value: '4 / 3' },
    { label: '16 / 9', value: '16 / 9' },
    { label: '21 / 9', value: '21 / 9' },
  ]

  const active = shallowRef('16 / 9')
</script>

<template>
  <div class="space-y-4">
    <div class="flex gap-2">
      <button
        v-for="r in ratios"
        :key="r.value"
        class="px-3 py-1 border rounded text-sm"
        :class="active === r.value ? 'bg-primary text-on-primary' : 'bg-surface'"
        @click="active = r.value"
      >
        {{ r.label }}
      </button>
    </div>

    <AspectRatio
      class="w-full bg-surface-tint rounded overflow-hidden"
      :ratio="active"
    >
      <div class="w-full h-full flex items-center justify-center text-on-surface-variant text-sm">
        {{ active }}
      </div>
    </AspectRatio>
  </div>
</template>

Anatomy

Anatomy
<script setup lang="ts">
  import { AspectRatio } from '@vuetify/v0'
</script>

<template>
  <AspectRatio />
</template>

Examples

Compose with Image

Wrap Image.Root in AspectRatio to pin the load frame to a fixed width-to-height ratio. The placeholder, fallback, and loaded image all share the same reserved box — so the layout never reflows as the image transitions through idle → loading → loaded or drops into error.

Composition

Use controls to zoom and pan. Click outside or press Escape to close.

Composition

This composition is the recommended pattern for content images whose natural dimensions vary, or that come from a CMS where the source’s intrinsic size isn’t known at authoring time. Instead of hard-coding width/height attributes that may not match the final media, let the container enforce the frame and let the image cover it via object-cover.

Two tradeoffs to know about:

  • The child must fill the frame. Use w-full h-full on Image.Img (or absolute positioning) so it stretches to the reserved box — otherwise the box is taller than the rendered image and looks broken.

  • A single ratio applies to every descendant. If you need different ratios per breakpoint, swap the :ratio prop with a responsive expression (computed driven by useBreakpoints) rather than layering multiple AspectRatio wrappers.

Pairs naturally with useImage when you’re driving the state machine manually, and with useIntersectionObserver when combining native lazy loading (loading="lazy") with a reserved frame.

FileRole
ResponsiveImage.vueReusable wrapper — AspectRatio around Image.Root with placeholder, fallback, and object-cover image
responsive.vueEntry point rendering images at two different ratios side-by-side (16 / 9 landscape and 1 square)
Landscape photo
Square photo

Recipes

Video embed

vue
<template>
  <AspectRatio :ratio="16 / 9" class="w-full">
    <iframe
      class="w-full h-full"
      src="https://www.youtube.com/embed/..."
    />
  </AspectRatio>
</template>

Square thumbnail grid

vue
<template>
  <div class="grid grid-cols-3 gap-2">
    <AspectRatio v-for="photo in photos" :key="photo.id" :ratio="1">
      <img :src="photo.src" class="w-full h-full object-cover" />
    </AspectRatio>
  </div>
</template>

Number or string

ratio accepts either form. Both produce the same output:

vue
<template>
  <AspectRatio :ratio="16 / 9" /> <!-- number: 1.777... -->
  <AspectRatio ratio="16 / 9" />  <!-- string -->
</template>

Accessibility

AspectRatio is a presentational primitive — it renders a <div> with an inline style and no semantics of its own. Any ARIA attributes belong on the content inside. Pass as to change the element when a different semantic wrapper is needed (e.g. as="figure").

Questions

API Reference

The following API details are for all variations of the AspectRatio component.

AspectRatio

Props

ratio

string | number | undefined

The aspect ratio as `width / height`. Accepts a number (`16 / 9`) or a CSS `aspect-ratio` string (`'16 / 9'`, `'1.777'`).

Default: 1

Slots

default

AspectRatioSlotProps
Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/