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="https://avatar.vercel.sh/shadcn1"
    alt="Photo"
    className="h-full w-full rounded-lg object-cover"
  />
</AspectRatio>

AspectRatio — wrapper qui force son enfant à respecter un ratio largeur/hauteur donné. Utile pour intégrer des images, vidéos ou iframes responsive sans jump de layout au chargement.

Implémentation : CSS aspect-ratio: W/H natif (Chrome 88+, Firefox 89+, Safari 15+). Aucun JS, aucun 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 Ratio largeur/hauteur (`16 / 9`, `1 / 1`, `9 / 16`…). Un string comme `"4/3"` est aussi accepté.
children ReactNode Le contenu — typiquement une image (<img className="h-full w-full object-cover" />) ou un iframe (<iframe className="h-full w-full" />).
className string undefined

Data Attributes

Attributs qu'on peut cibler en CSS custom pour override le style par état.

Attribute On Values Description
data-slot="aspect-ratio" AspectRatio root undefined

Accessibility

Purement décoratif — pas de sémantique ajoutée. Si le contenu est une image, garder son alt. Si c'est un iframe, garder son title. Pour la mise en page RTL, wrapper avec dir="rtl" sur un ancêtre.

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.