Aspect Ratio

Constrain children to a specific width-to-height ratio (e.g. 16/9 for video, 1/1 for square).

16 : 9
1 : 1
2 : 3

Installation

pnpm
pnpm dlx @hex-core/cli add aspect-ratio

Video embed (16:9)

Constrain a YouTube/Vimeo iframe to widescreen so the player scales with the column.

tsx
<AspectRatio ratio={16 / 9} className="overflow-hidden rounded-md bg-muted">
  <iframe
    src="https://www.youtube.com/embed/dQw4w9WgXcQ"
    title="Product walkthrough"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
    allowFullScreen
    className="h-full w-full border-0"
  />
</AspectRatio>

Photo card (4:3)

Wider-than-tall thumbnail for gallery or blog cards. Use object-cover to crop instead of distort.

tsx
<Card className="w-64 overflow-hidden">
  <AspectRatio ratio={4 / 3} className="bg-muted">
    <img
      src="/posts/2024-q3-roundup.jpg"
      alt="Three workstations on a shared desk under warm lighting"
      className="h-full w-full object-cover"
    />
  </AspectRatio>
  <div className="space-y-1 p-4">
    <p className="text-sm font-medium">Q3 product roundup</p>
    <p className="text-xs text-muted-foreground">8 min read</p>
  </div>
</Card>

API Reference

PropTypeDefaultDescription
ratio
number1Width-to-height ratio (e.g. 16/9 ≈ 1.778)

AI Guidance

When to use

Use when an image or iframe must maintain a specific ratio regardless of container width: video thumbnails, product images, hero banners, embeds.

When not to use

Don't use for content with known fixed dimensions (just use width/height). Don't use for text content (ratios don't make sense for prose).

Common mistakes

  • Passing ratio as a string instead of a number (use {16/9}, not '16/9')
  • Forgetting that children must fill 100% width + height (add object-cover or similar)
  • Forgetting that ratio is width-over-height — ratio={4/3} is wider than tall, NOT a 4:3 portrait. For portrait orientation, pass ratio={3/4}.

Accessibility

AspectRatio is purely structural. Ensure inner <img> has alt text and inner <iframe> has a descriptive title.

Related components

Token budget: 200