bx

Aspect Ratio

Displays content within a desired ratio.

Photo
tsx
<AspectRatio ratio={16 / 9} className="w-full max-w-sm rounded-lg bg-muted">
  <img
    src="/avatars/01.png"
    alt="Photo"
    className="h-full w-full rounded-lg object-cover"
  />
</AspectRatio>

AspectRatio is a wrapper that forces its child to a given width/height ratio. Useful for embedding responsive images, videos or iframes without layout shift on load.

Implementation: native CSS aspect-ratio: W/H (Chrome 88+, Firefox 89+, Safari 15+). No JS, no padding hack.

Installation

Terminal
$ bext ui add aspect-ratio

Usage

tsx
import { AspectRatio } from "@bext-stack/ui/primitives"

<AspectRatio ratio={16 / 9} className="w-full max-w-sm rounded-lg bg-muted">
  <img src="/photo.jpg" alt="Photo" className="h-full w-full object-cover rounded-lg" />
</AspectRatio>

Anatomy

<AspectRatio ratio={16 / 9}>{child}</AspectRatio>

API Reference

AspectRatio

Prop Type Default Description
ratio number | string "1/1" Width/height ratio (`16 / 9`, `1 / 1`, `9 / 16`…). A string such as `"4/3"` is also accepted.
children ReactNode — The content, typically an image (<img className="h-full w-full object-cover" />) or an iframe (<iframe className="h-full w-full" />).
className string — Extra classes on the wrapper (relative w-full overflow-hidden), for example a rounded corner or a background.

Data Attributes

Attributes you can target in custom CSS to override the style for each state.

Attribute On Values Description
data-slot="aspect-ratio" AspectRatio root — Stable selector for custom styling. The ratio itself is an inline aspect-ratio style.

Accessibility

Purely decorative, no semantics added. If the content is an image, keep its alt. If it is an iframe, keep its title. For RTL layout, set dir="rtl" on an ancestor.

Examples

Square

Photo
tsx
<AspectRatio ratio={1 / 1} className="w-full max-w-[12rem] rounded-lg bg-muted">
  <img src="…" alt="Photo" className="h-full w-full rounded-lg object-cover" />
</AspectRatio>

Portrait

Photo
tsx
<AspectRatio ratio={9 / 16} className="w-full max-w-[10rem] rounded-lg bg-muted">
  <img src="…" alt="Photo" className="h-full w-full rounded-lg object-cover" />
</AspectRatio>

RTL

منظر طبيعي جميل
منظر طبيعي جميل
tsx
<figure className="w-full max-w-sm" dir="rtl">
  <AspectRatio ratio={16 / 9} className="rounded-lg bg-muted">
    <img src="…" alt="منظر طبيعي جميل" className="h-full w-full rounded-lg object-cover" />
  </AspectRatio>
  <figcaption className="mt-2 text-center text-sm text-muted-foreground">
    منظر طبيعي جميل
  </figcaption>
</figure>

YouTube embed (16 / 9)

tsx
<AspectRatio ratio={16 / 9} className="rounded-lg overflow-hidden">
  <iframe
    src="https://www.youtube.com/embed/..."
    className="h-full w-full"
    allow="autoplay; encrypted-media"
    allowFullScreen
  />
</AspectRatio>
Try it live Open in play

Edit this example live in the bext playground. It compiles and runs entirely in your browser.

src/app/page.tsx 1 file · react · runs in your browser
The React idiom: same UI, for comparison.