aspect-ratio
Displays content within a desired ratio.
Philosophy
Responsive media needs dimensional constraints. AspectRatio solves the CSS aspect-ratio problem with a clean component API, preventing layout shifts when images and videos load. The ratio prop is the only knob you need - everything else is handled by the container's CSS.
How It's Built
Installation
npx @gentleduck/cli add aspect-ratio
npx @gentleduck/cli add aspect-ratio
Usage
import Image from "next/image"
import { AspectRatio } from "@/components/ui/aspect-ratio"
<div className="w-[450px]">
<AspectRatio ratio={16 / 9}>
<Image src="..." alt="Image" className="rounded-md object-cover" />
</AspectRatio>
</div>
RTL Support
Set the direction once with DirectionProvider (or <html dir="rtl">) and the aspect ratio follows it. No dir prop or rtl: classes needed.
Motion
Use MotionAspectRatio for a smooth scale + blur entrance animation powered by motion. The content scales from 0.95 and unblurs on mount.
motion package. Use MotionAspectRatio instead of AspectRatio. Same props. Note: MotionAspectRatio adds an animated div wrapper around AspectRatio; the inner Slot/asChild behavior is unchanged.API Reference
AspectRatio
| Prop | Type | Default | Description |
|---|---|---|---|
dir | 'ltr' | 'rtl' | - | Text direction override. Resolved via useDirection (dir prop -> DirectionProvider -> <html dir>). |
ratio | number | (required) | Aspect ratio of the container, e.g. 16/9, 4/3 |
className | string | -- | Additional class names to apply to the container |
style | React.CSSProperties | -- | Inline styles applied to the container (aspect-ratio is merged automatically) |
children | React.ReactNode | -- | Child element to render inside the aspect-ratio container |
...props | React.ComponentPropsWithoutRef<typeof Slot> | - | Additional props inherited from Slot. |
Uses a Slot wrapper, so the child element receives the aspect-ratio styles.
MotionAspectRatio
Wraps AspectRatio in an animated div that scales from 0.95 with 8px blur fade on mount, using the scaleIn preset and a bouncy spring transition (stiffness 500, damping 28). The wrapped AspectRatio still renders its child via Slot internally. Requires the motion package.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | AspectRatioProps | - | All props from AspectRatio are supported |