---
name: aspect-ratio
title: Aspect Ratio
url: https://ui.frontic.com/components/ui/aspect-ratio.md
tier: ui
install: npx @frontic/ui add aspect-ratio
files:
  - components/ui/aspect-ratio/AspectRatio.vue
  - components/ui/aspect-ratio/index.ts
dependencies:
  - "@vueuse/core"
  - reka-ui
---

# Aspect Ratio

Keeps its content at a fixed width-to-height ratio, such as a square product image or a 16:9 video.

## Install

```sh
npx @frontic/ui add aspect-ratio
```

npm packages: `@vueuse/core`, `reka-ui`

## Examples

```vue
<script setup lang="ts">
import { AspectRatio } from '@/components/ui/aspect-ratio'
</script>

<template>
  <div class="w-sm max-w-full">
    <AspectRatio :ratio="16 / 9">
      <img src="https://static.frontic.com/cdn-cgi/image/format=auto/ui/banners/mens-jackets.png" alt="A man in a colour-block ski jacket in front of snowy mountains" class="size-full object-cover" />
    </AspectRatio>
  </div>
</template>
```

## API reference

### AspectRatio

Keeps its content at a fixed width-to-height ratio.

`data-slot="aspect-ratio"` · `AspectRatio.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `ratio` | `number` | `1` | The desired ratio. Eg: 16/9 |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

| Slot | Slot props | Description |
| --- | --- | --- |
| `default` | `{ aspect: number; }` | Holds the content kept at the ratio; gets the ratio. |

## Styling

| Part | Recipe |
| --- | --- |
| `default` | [`aspect-ratio`](https://ui.frontic.com/recipes/aspect-ratio.json) |

## Source

`components/ui/aspect-ratio/AspectRatio.vue`

```vue
<script lang="ts">
/** Keeps its content at a fixed width-to-height ratio. */
export default {}
</script>

<script setup lang="ts">
import type { AspectRatioProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { AspectRatio, useForwardProps } from 'reka-ui'

const props = defineProps<AspectRatioProps & { class?: HTMLAttributes['class'] }>()

defineSlots<{
  /** Holds the content kept at the ratio; gets the ratio. */
  default?: (props: { aspect: number }) => unknown
}>()

const delegatedProps = reactiveOmit(props, 'class')
const forwarded = useForwardProps(delegatedProps)
</script>

<template>
  <AspectRatio v-slot="slotProps" data-slot="aspect-ratio" v-bind="forwarded" :class="['fui-aspect-ratio overflow-hidden', props.class]">
    <slot v-bind="slotProps" />
  </AspectRatio>
</template>
```
