<!-- Protocore Design System — AspectRatio -->
# AspectRatio

- **Category:** Layout (`layout`)
- **Slug:** `layout/aspect-ratio`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { AspectRatio } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/layout/aspect-ratio

> A box that locks its content to a fixed width-to-height ratio.

## When to use it

Use `AspectRatio` wherever a media slot must hold its shape before its content has dimensions — thumbnails, cover art, embedded video, chart placeholders, map tiles. It prevents cumulative layout shift: the box claims its height from the ratio, not from the image. It controls **shape only** — it doesn't crop or bound width, so pair it with a `Grid` cell or a width-constrained parent. If you just need a plain block with padding, this isn't it; reach for a `Card` or a styled `div`.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `children` | `ReactNode` | no | — | Media/content to fit the box (images, video and iframes fill and cover). |
| `className` | `string` | no | — | — |
| `ratio` | `number` | no | `16 / 9` | Width-to-height ratio, e.g. `16 / 9` or `1`. |
| `style` | `CSSProperties` | no | — | — |

## Examples

### Basics

`AspectRatio` reserves space at a fixed ratio (default `16 / 9`) so the layout doesn't reflow while media loads. Images, video and iframes inside fill and cover the box.

```tsx
import { AspectRatio, Text } from "@protocore/pds";

export default function AspectRatioBasics() {
  return (
    <div style={{ maxWidth: 360 }}>
      <AspectRatio
        ratio={16 / 9}
        style={{
          background: "var(--pds-color-surface-2)",
          display: "grid",
          placeItems: "center",
          outline: "1px solid var(--pds-border-faint)",
        }}
      >
        <Text mono size="sm" color="secondary">
          16 / 9
        </Text>
      </AspectRatio>
    </div>
  );
}
```

### Common ratios

Pass any numeric ratio — `1` for square thumbnails, `4 / 3` for diagrams, `21 / 9` for wide banners.

```tsx
import { AspectRatio, Grid, Text } from "@protocore/pds";

const RATIOS: Array<{ label: string; ratio: number }> = [
  { label: "1 / 1", ratio: 1 },
  { label: "4 / 3", ratio: 4 / 3 },
  { label: "21 / 9", ratio: 21 / 9 },
];

export default function AspectRatioRatios() {
  return (
    <Grid columns={3} gap={3}>
      {RATIOS.map(({ label, ratio }) => (
        <AspectRatio
          key={label}
          ratio={ratio}
          style={{
            background: "var(--pds-color-surface-2)",
            display: "grid",
            placeItems: "center",
            outline: "1px solid var(--pds-border-faint)",
          }}
        >
          <Text mono size="sm" color="secondary">
            {label}
          </Text>
        </AspectRatio>
      ))}
    </Grid>
  );
}
```

## Do & don't

**Do**

- Wrap images, video and iframes so the slot holds its shape while loading.
- Use it inside Grid cells to keep a card wall's media uniform.
- Match the ratio to the source aspect to avoid unwanted cropping.

**Don't**

- Rely on it to set width — constrain that with the parent (Grid cell, Container).
- Use it for plain text blocks; it locks height to width, which text rarely wants.
- Nest interactive controls whose height must grow with content inside it.

## Accessibility

**Notes**

- AspectRatio is a presentational `<div>` and adds no semantics.
- Give the media it wraps its own accessible name (e.g. `alt` on an `<img>`).

## Related

`grid`, `container`, `section`, `card`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
