Aspect Ratio
ui-aspect-ratio is a block that sizes its height from its width with the CSS aspect-ratio property and clips
anything that overflows. It fills the width of its container, so size it with a wrapper. A slotted <img>,
<video> or <iframe> is stretched to fill the box with object-fit: cover. Put the radius and background on
the content, not on the box.
16 / 9
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Aspect Ratio demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-medium {
width: min(100%, calc(var(--spacing) * 120));
}
.demo-tile {
display: grid;
place-items: center;
box-sizing: border-box;
height: 100%;
min-height: calc(var(--spacing) * 16);
padding: calc(var(--spacing) * 4);
border-radius: var(--radius-lg);
background: var(--muted);
font-size: var(--text-sm);
font-weight: var(--font-weight-medium);
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/aspect-ratio.html"></import-element>
<div class="demo-medium">
<ui-aspect-ratio ratio="16 / 9">
<div class="demo-tile">16 / 9</div>
</ui-aspect-ratio>
</div>
</body>
</html>Examples
Ratios
ratio takes any value the CSS aspect-ratio property accepts, such as 1 / 1, 4 / 3 or 2.35.
21 / 9
4 / 3
1 / 1
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Aspect Ratio demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
.demo-stack {
display: grid;
gap: calc(var(--spacing) * 4);
}
.demo-tile {
display: grid;
place-items: center;
box-sizing: border-box;
height: 100%;
min-height: calc(var(--spacing) * 16);
padding: calc(var(--spacing) * 4);
border-radius: var(--radius-lg);
background: var(--muted);
font-size: var(--text-sm);
font-weight: var(--font-weight-medium);
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/aspect-ratio.html"></import-element>
<div class="demo-narrow demo-stack">
<ui-aspect-ratio ratio="21 / 9">
<div class="demo-tile">21 / 9</div>
</ui-aspect-ratio>
<ui-aspect-ratio ratio="4 / 3">
<div class="demo-tile">4 / 3</div>
</ui-aspect-ratio>
<ui-aspect-ratio ratio="1 / 1">
<div class="demo-tile">1 / 1</div>
</ui-aspect-ratio>
</div>
</body>
</html>Image
A slotted image covers the whole box and is cropped to the ratio.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Aspect Ratio demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
.demo-image {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
border-radius: var(--radius-lg);
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/aspect-ratio.html"></import-element>
<div class="demo-narrow">
<ui-aspect-ratio ratio="4 / 3">
<img class="demo-image" alt="A mountain range at sunset" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 200'%3E%3Crect width='400' height='200' fill='%23f4a261'/%3E%3Cpath d='M0 200 120 70l70 80 60-50 150 100z' fill='%23264653'/%3E%3Ccircle cx='300' cy='60' r='28' fill='%23e9c46a'/%3E%3C/svg%3E">
</ui-aspect-ratio>
</div>
</body>
</html>Video embed
<ui-aspect-ratio ratio="16 / 9">
<iframe src="https://www.youtube-nocookie.com/embed/VIDEO_ID" title="Product tour" allowfullscreen></iframe>
</ui-aspect-ratio>API
Parts
| Part | Slot | Renders |
|---|---|---|
ui-aspect-ratio |
(default) | A full-width block at the given ratio that clips overflow. Its default slot takes any content. <img>, <video> and <iframe> fill the box and use object-fit: cover. |
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
ratio |
string | "16 / 9" |
Width-to-height ratio, as a CSS aspect-ratio value. |
CSS parts
None. The box renders only a slot.
CSS states and custom properties
The ratio is applied through the reactive custom property --attr-ratio, which mirrors the ratio attribute.
Accessibility
The element adds no semantics. Give images an alt text and iframes a title.