# AspectRatio

> A box that keeps a fixed width-to-height ratio as it resizes, for video embeds, maps, cover images and thumbnails; direct img, video and iframe children fill it.

Source: https://docs.nasaqui.com/components/aspect-ratio

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/aspect-ratio.json
```

A `div` with CSS `aspect-ratio`. It reserves the height before media loads, so the page does not jump.

## When to use

- Video and map embeds, cover images, thumbnails in a grid.

## When not to use

- Images with known `width` and `height` attributes: the browser already reserves their space.
- Text content: let it set its own height.

## Import

```tsx
import { AspectRatio } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"
```

## Quick start

```tsx
import { AspectRatio } from "@fadymondy/nasaq/web";

export function Intro() {
  return (
    <AspectRatio ratio={16 / 9} className="rounded-card border border-border">
      <iframe src="https://www.youtube-nocookie.com/embed/VIDEO_ID" title="Product tour" allowFullScreen />
    </AspectRatio>
  );
}
```

## Anatomy

```
AspectRatio                     data-slot="aspect-ratio", style="aspect-ratio: <ratio>"
└─ img | video | iframe         absolutely fills the box (img and video use object-cover)
```

Other children flow normally inside the box.

## API

**AspectRatio**: every `div` prop, plus:

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `ratio` | `number` | `16 / 9` | Width over height: `16 / 9`, `4 / 3`, `1`. |

## Accessibility

- Give every `iframe` a `title` and every `img` an `alt`; the box adds no semantics.

## RTL & i18n

- Nothing to mirror.

## Styling & tokens

- No visual style of its own. Add `rounded-card` and `border-border`; `overflow-hidden` is set so corners clip.

## Do / Don't

- Do pick the media's real ratio so nothing is cropped by surprise.
- Don't put long text inside; it overflows on narrow screens.

## Related

- [`Card`](https://docs.nasaqui.com/components/card)
- [`MapView`](https://docs.nasaqui.com/components/map-view)

## Lab

https://docs.nasaqui.com/?path=/docs/components-layout-aspect-ratio--docs

## Code

### React

```tsx
import { AspectRatio } from "@fadymondy/nasaq/web";

export function Intro() {
  return (
    <AspectRatio ratio={16 / 9} className="rounded-card border border-border">
      <iframe src="https://www.youtube-nocookie.com/embed/VIDEO_ID" title="Product tour" allowFullScreen />
    </AspectRatio>
  );
}
```

### shadcn

```tsx
import { AspectRatio } from "@/components/ui/aspect-ratio";

export function Intro() {
  return (
    <AspectRatio ratio={16 / 9} className="rounded-card border border-border">
      <iframe src="https://www.youtube-nocookie.com/embed/VIDEO_ID" title="Product tour" allowFullScreen />
    </AspectRatio>
  );
}
```

### Vue

```vue
<script setup lang="ts">
import { NqAspectRatio } from "@fadymondy/nasaq/vue";
</script>

<template>
  <NqAspectRatio :ratio="16 / 9" class="rounded-card border border-border">
    <iframe src="https://www.youtube-nocookie.com/embed/VIDEO_ID" title="Product tour" allowfullscreen />
  </NqAspectRatio>
</template>
```

### Blade

```blade
<x-nq::aspect-ratio :ratio="16 / 9" class="rounded-card border border-border">
    <iframe src="https://www.youtube-nocookie.com/embed/VIDEO_ID" title="Product tour" allowfullscreen></iframe>
</x-nq::aspect-ratio>
```

### HTML + Alpine

```html
<div data-slot="aspect-ratio" style="aspect-ratio: 1.7777777777778"
    class="relative w-full overflow-hidden [&>iframe]:absolute [&>iframe]:inset-0 [&>iframe]:size-full [&>img]:absolute [&>img]:inset-0 [&>img]:size-full [&>img]:object-cover [&>video]:absolute [&>video]:inset-0 [&>video]:size-full [&>video]:object-cover rounded-card border border-border"><iframe src="https://www.youtube-nocookie.com/embed/VIDEO_ID" title="Product tour" allowfullscreen></iframe></div>
```
