Skip to content

Aspect Ratio

Stable

Holds media to a fixed width-to-height ratio, reserving its space before the content loads.

Meridian16 : 9

Installation

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/aspect-ratio.json

Usage

import { AspectRatio } from "@/components/ui/aspect-ratio"
<AspectRatio ratio={16 / 9} className="overflow-hidden rounded-xl">
  <img src="/cover.jpg" alt="…" className="size-full object-cover" />
</AspectRatio>

ratio is width divided by height. The component is a positioned <div> sized with the CSS aspect-ratio property — no JavaScript, no padding hacks — so it works in server components and never shifts after hydration.

Examples

Common ratios

Choose the ratio from the content, then keep it consistent across a collection so grids line up.

1:1
Avatars, products
4:3
Photos, thumbnails
3:2
Editorial images
16:9
Video, hero media
21:9
Cinematic banners

With Next.js Image

Use fill so the image takes the box's size, and object-cover to crop instead of stretching. Pass sizes so the browser downloads the right resolution.

import Image from "next/image"

<AspectRatio ratio={16 / 9} className="overflow-hidden rounded-xl bg-muted">
  <Image
    src="/showcase/dashboard.png"
    alt="The analytics dashboard in dark mode"
    fill
    sizes="(min-width: 768px) 50vw, 100vw"
    className="object-cover"
  />
</AspectRatio>

Video

Video and embeds should reserve their frame before they load. Overlay controls and metadata with absolute positioning — the box is already relative.

12:48
Designing with tokensprfct Talks · Episode 4
<AspectRatio ratio={16 / 9} className="overflow-hidden rounded-xl">
  <iframe
    src="https://www.youtube-nocookie.com/embed/…"
    title="Designing with tokens"
    allow="accelerometer; encrypted-media; picture-in-picture"
    allowFullScreen
    className="absolute inset-0 size-full"
  />
</AspectRatio>

Square grid

A 1:1 ratio keeps avatars, product shots and thumbnails uniform even when the source images aren't.

  • Ana
  • Jonas
  • Maya
  • Theo
  • Iris
  • Lena
  • Omar
  • Eli

Card media

Put the ratio box first in a card with pt-0 on the card, and the media runs edge to edge with the card's rounded corners.

New
Amber desk lamp
Hand-finished brass, warm dimmable light.
$189

Guidelines

When to use

  • For images, video, maps and embeds whose container width changes with the layout.
  • In grids and carousels, to keep every tile the same shape.
  • Wherever late-loading media would otherwise push content down.

When not to use

  • For text or UI whose height depends on its content — fixing the ratio will clip or leave gaps.
  • When the container already has fixed pixel dimensions; set them directly.

Crop, don't distort

Media inside a ratio box should use object-cover (crop to fill) or object-contain (letterbox), never the default stretch.

Do.object-cover fills the frame and keeps proportions.
Don’t.Stretched media looks broken, no matter how good the photo is.

Accessibility

Aspect Ratio is purely presentational; what matters is the media inside it.

  • Images need alt text that says what the image shows, or alt="" when it's decorative.
  • Video needs captions, and embeds need a title that names the content.
  • Layout stability. Reserving space prevents content from jumping as media loads, which helps everyone — and especially people using magnification or reading slowly.

API reference

AspectRatio

Renders a <div> with position: relative and aspect-ratio set from ratio. Accepts every <div> prop.

PropTypeDefault
ratiorequired

Width divided by height, e.g. 16 / 9 or 1.

numberNo default
className

Rounding, overflow and background for the frame.

stringNo default