AspectRatio

Constrains a child element to a given aspect ratio using a CSS custom property. A pure div-based implementation that uses aspect-(--ratio) — no padding-top hack required.

Anatomy

A single <AspectRatio ratio={n}> wrapper. The ratio prop is a number (width ÷ height). The child fills the constrained box using object-cover or absolute inset-0.

16:9

Common Ratios

Pass any numeric ratio to the ratio prop. Express it as a fraction for readability.

16:9

Widescreen video, hero images

4:3

Traditional display, old monitors

1:1

Profile photos, square thumbnails

3:2

Photography standard (DSLR)

2:3

Portrait / mobile screens

21:9

Ultrawide / cinematic

With Image

Place an <img> with object-cover w-full h-full inside the ratio wrapper to crop it to the target aspect.

16:9
1:1
2:3

Design Guidelines

Do

  • Use for image and video containers. AspectRatio prevents layout shift while media loads by reserving the correct space.
  • Express the ratio as a fraction. ratio={16 / 9} is more readable than ratio={1.777}.
  • Combine with object-cover on images. This ensures the image fills the box without distortion.

Don't

  • Don't use for text content. Text has natural height; forcing an aspect ratio will cause overflow or awkward whitespace.
  • Don't use without constraining the wrapper width. Without a fixed width, the ratio box will expand to fill its parent.
  • Don't mix absolute-positioned children with padding offsets. The component uses aspect-(--ratio) — the child should fill via absolute inset-0 or w-full h-full.

Developer Reference

API

  • ratio (required) — a number representing width ÷ height. Stored as a CSS custom property --ratio.
  • The component renders a plain <div> — all standard div props are forwarded.
  • Children should use w-full h-full or absolute inset-0 to fill the box correctly.

Usage

import { AspectRatio } from "@/components/ui/aspect-ratio"

// Image at 16:9
<AspectRatio ratio={16 / 9}>
  <img
    src="/hero.jpg"
    alt="Hero"
    className="h-full w-full rounded-lg object-cover"
  />
</AspectRatio>

// Square placeholder
<AspectRatio ratio={1}>
  <div className="flex h-full items-center justify-center bg-muted rounded-lg">
    1:1
  </div>
</AspectRatio>

// Portrait / mobile frame
<AspectRatio ratio={2 / 3}>
  <div className="h-full w-full rounded-lg bg-muted" />
</AspectRatio>