Skip to content

Aspect Ratio

A box that keeps a fixed width to height ratio for what it holds, such as an image, a video or a map. It reserves the space before the content loads, so the page does not jump.

Layoutv0.1.0experimentalWCAG 2.2 AAView spec
16:9 video area
import { AspectRatio } from "@rdloom/react";

export default function AspectRatioVideoExample() {
  return (
    <div className="flex w-full justify-center">
      <div className="w-[28rem] max-w-full">
        <AspectRatio ratio="video" rounded>
          <div className="flex size-full items-center justify-center bg-gradient-to-br from-[var(--rd-color-surface-subtle)] to-[var(--rd-color-border-default)] text-sm text-[var(--rd-color-text-muted)]">
            16:9 video area
          </div>
        </AspectRatio>
      </div>
    </div>
  );
}

Installation

npx rdloom add aspect-ratio

Copies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes.

Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/aspect-ratio.json

Works, but without upgrade tracking.

Usage

import { AspectRatio } from "@rdloom/react";

<div className="flex w-full justify-center">
  <div className="w-[28rem] max-w-full">
    <AspectRatio ratio="video" rounded>
      <div className="flex size-full items-center justify-center bg-gradient-to-br from-[var(--rd-color-surface-subtle)] to-[var(--rd-color-border-default)] text-sm text-[var(--rd-color-text-muted)]">
        16:9 video area
      </div>
    </AspectRatio>
  </div>
</div>

Square

import { AspectRatio } from "@rdloom/react";

export default function AspectRatioSquareExample() {
  return (
    <div className="flex w-full justify-center">
      <div className="w-48">
        <AspectRatio ratio="square" rounded>
          <div
            role="img"
            aria-label="Image placeholder"
            className="size-full bg-gradient-to-tr from-[var(--rd-color-action-primary)] to-[var(--rd-color-surface-subtle)]"
          />
        </AspectRatio>
      </div>
    </div>
  );
}

Portrait

3:4 cover
import { AspectRatio } from "@rdloom/react";

export default function AspectRatioPortraitExample() {
  return (
    <div className="flex w-full justify-center">
      <div className="w-40">
        <AspectRatio ratio="portrait" rounded>
          <div className="flex size-full items-end bg-gradient-to-b from-[var(--rd-color-surface-subtle)] to-[var(--rd-color-border-strong)] p-3 text-sm text-[var(--rd-color-text-default)]">
            3:4 cover
          </div>
        </AspectRatio>
      </div>
    </div>
  );
}

API Reference

Defined by the spec. Components also accept the props of the React Aria component they wrap.

PropTypeDefault
ratio

Width divided by height as a number (1.5), a "16/9" string, or a preset: square 1/1, video 16/9, photo 3/2, wide 21/9, portrait 3/4.

number | "square" | "video" | "photo" | "wide" | "portrait" | `${number}/${number}`"video"
rounded

Rounds the corners with the control radius.

booleanfalse
children

The content. Images, video and iframes are stretched to fill the box and cropped to cover it.

nodenone

Accessibility

Role none, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.

Keyboard

  • Not interactive: it adds no tab stops

Screen readers announce

  • Transparent to screen readers; only the content inside is announced

What your code must do

  • The box adds no role or name; the content inside carries its own, such as alt text on an image
  • Content that is cropped must not lose information that matters: pick a ratio that fits it

Guidelines

Use it when

  • Media whose size is not known before it loads
  • A grid of tiles that must line up
  • A video or map embed that should scale with its container

Avoid it when

  • Text content: it can overflow the fixed box
  • Content that must never be cropped, such as a chart with labels at the edges

Don't

  • Putting long text inside, which gets clipped
  • Setting a height on the box, which fights the ratio

Design tokens

The semantic tokens this component uses. Change them once and every component follows; see Design tokens.

  • --rd-radius-control