Aspect Ratio
Container that enforces a width-to-height ratio on its content, for images, videos, and embedded media.
<arc-aspect-ratio>Overview
AspectRatio is a layout primitive that constrains its children to a specified width-to-height proportion using the CSS aspect-ratio property. Pass a ratio string like "16/9", "4/3", or "1/1" and the container keeps that shape at any width. Slotted children (images, videos, iframes) are sized to fill the container with object-fit: cover, so there is no letterboxing or stretching.
AspectRatio prevents layout shift (CLS) caused by media loading. It reserves the exact space an image or video will occupy before it loads, which avoids page reflows that hurt user experience and Core Web Vitals scores. The container's width is always 100% of its parent and the height is derived from the ratio, so it works in fluid grid layouts.
The ratio prop accepts any valid W/H format including decimal values like "2.35/1" for cinematic widescreen. If an invalid format is provided, the component falls back to 16/9. The container applies the theme's medium border radius and clips overflow, so media gets rounded corners without extra styling.
Guidelines
When to use
- Use AspectRatio around images and videos to prevent layout shift during page load
- Choose standard ratios that match your media: `16/9` for video, `4/3` for photos, `1/1` for avatars or thumbnails
- Place AspectRatio inside grid or flex containers where the width is determined by the layout
- Use decimal ratios like `2.35/1` for cinematic or ultrawide content when needed
- Combine with lazy loading on images; the space is reserved before the image loads
When not to use
- Do not use AspectRatio when the content has its own intrinsic dimensions and layout shift is not a concern
- Do not place text-heavy content inside AspectRatio; it clips overflow and does not scroll
- Do not set both a fixed height and AspectRatio on the same element; they will conflict
- Do not use ratio values with zero in the denominator (e.g. `16/0`); the component falls back to 16/9
- Avoid nesting multiple AspectRatio components; the inner one is constrained by both ratios unpredictably
Features
- Enforces a consistent aspect ratio using the CSS `aspect-ratio` property with a `W/H` string prop
- Slotted children automatically sized to fill with `width: 100%`, `height: 100%`, and `object-fit: cover`
- Prevents content layout shift (CLS) by reserving space before media loads
- Supports any valid ratio including standard formats (`16/9`, `4/3`, `1/1`) and decimals (`2.35/1`)
- Falls back to `16/9` if the ratio string is invalid or malformed
- Applies `border-radius: var(--radius-md)` with overflow clipping for rounded media corners
- Full-width container that fills its parent, which suits responsive grid cells
- Wrapper with no JavaScript interaction; layout is pure CSS
Preview
Usage
<arc-aspect-ratio ratio="16/9">
<img src="/hero.jpg" alt="Hero banner" />
</arc-aspect-ratio>
<!-- Square thumbnail -->
<arc-aspect-ratio ratio="1/1">
<img src="/avatar.jpg" alt="User avatar" />
</arc-aspect-ratio>import { AspectRatio } from '@arclux/arc-ui-react';
export default function Example() {
return (
<>
<AspectRatio ratio="16/9">
<img src="/hero.jpg" alt="Hero banner" />
</AspectRatio>
{/* Square thumbnail */}
<AspectRatio ratio="1/1">
<img src="/avatar.jpg" alt="User avatar" />
</AspectRatio>
</>
);
}<script setup>
import { AspectRatio } from '@arclux/arc-ui-vue';
</script>
<template>
<AspectRatio ratio="16/9">
<img src="/hero.jpg" alt="Hero banner" />
</AspectRatio>
<!-- Square thumbnail -->
<AspectRatio ratio="1/1">
<img src="/avatar.jpg" alt="User avatar" />
</AspectRatio>
</template><script>
import { AspectRatio } from '@arclux/arc-ui-svelte';
</script>
<AspectRatio ratio="16/9">
<img src="/hero.jpg" alt="Hero banner" />
</AspectRatio>
<!-- Square thumbnail -->
<AspectRatio ratio="1/1">
<img src="/avatar.jpg" alt="User avatar" />
</AspectRatio>import { Component } from '@angular/core';
import { AspectRatio } from '@arclux/arc-ui-angular';
@Component({
imports: [AspectRatio],
template: `
<arc-aspect-ratio ratio="16/9">
<img src="/hero.jpg" alt="Hero banner" />
</arc-aspect-ratio>
<!-- Square thumbnail -->
<arc-aspect-ratio ratio="1/1">
<img src="/avatar.jpg" alt="User avatar" />
</arc-aspect-ratio>
`,
})
export class MyComponent {}import { AspectRatio } from '@arclux/arc-ui-solid';
export default function Example() {
return (
<>
<AspectRatio ratio="16/9">
<img src="/hero.jpg" alt="Hero banner" />
</AspectRatio>
{/* Square thumbnail */}
<AspectRatio ratio="1/1">
<img src="/avatar.jpg" alt="User avatar" />
</AspectRatio>
</>
);
}import { AspectRatio } from '@arclux/arc-ui-preact';
export default function Example() {
return (
<>
<AspectRatio ratio="16/9">
<img src="/hero.jpg" alt="Hero banner" />
</AspectRatio>
{/* Square thumbnail */}
<AspectRatio ratio="1/1">
<img src="/avatar.jpg" alt="User avatar" />
</AspectRatio>
</>
);
}<!-- Auto-generated by @arclux/prism — do not edit manually -->
<!-- arc-aspect-ratio — requires aspect-ratio.css + tokens.css (or arc-ui.css) -->
<div class="arc-aspect-ratio">
<div
class="aspect-ratio"
style="aspect-ratio: _aspect Ratio;"
>
<div class="aspect-ratio__inner">
AspectRatio
</div>
</div>
</div><!-- Auto-generated by @arclux/prism — do not edit manually -->
<!-- arc-aspect-ratio — self-contained, no external CSS needed -->
<div class="arc-aspect-ratio" style="display: block">
<div
style="position: relative; width: 100%; overflow: hidden; border-radius: 10px"
style="aspect-ratio: _aspect Ratio;"
>
<div style="width: 100%; height: 100%">
AspectRatio
</div>
</div>
</div>API
DEFAULT_RATIOstring'16/9'- The documented default, and what anything unusable normalises to.
ratiostring'16/9'- Aspect ratio as a
W/Hstring. Supports integers and decimals. An unparseable value, or one with a zero on either side, is normalised **on the property** to16/9, so readingratioback always gives the ratio the component is actually using.