Skip to content
edmi-ui

Aspect ratio

Locks content to a ratio so layouts do not jump while loading.

StackBlitz ↗StackBlitz ↗StackBlitz ↗
16 / 9
1 / 1
9 / 16
16 / 9
1 / 1
9 / 16
16 / 9
1 / 1
9 / 16
Terminal window
npx shadcn@latest add @edmi-ui/aspect-ratio
Terminal window
pnpm dlx shadcn@latest add @edmi-ui/aspect-ratio
Terminal window
yarn dlx shadcn@latest add @edmi-ui/aspect-ratio
Terminal window
bunx shadcn@latest add @edmi-ui/aspect-ratio

Pick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.

Terminal window
npx shadcn-vue@latest add @edmi-ui/aspect-ratio
Terminal window
pnpm dlx shadcn-vue@latest add @edmi-ui/aspect-ratio
Terminal window
yarn dlx shadcn-vue@latest add @edmi-ui/aspect-ratio
Terminal window
bunx shadcn-vue@latest add @edmi-ui/aspect-ratio

Pick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.

Terminal window
npx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/aspect-ratio.json
Terminal window
pnpm dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/aspect-ratio.json
Terminal window
yarn dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/aspect-ratio.json
Terminal window
bunx --bun shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/aspect-ratio.json

Pick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.

import { AspectRatio } from "@/components/ui/aspect-ratio";
<div className="flex items-start gap-4">
{[
["16 / 9", 16 / 9, "w-52"],
["1 / 1", 1, "w-28"],
["9 / 16", 9 / 16, "w-20"],
].map(([label, ratio, width]) => (
<AspectRatio
key={label as string}
ratio={ratio as number}
className={`${width} flex items-center justify-center rounded-lg border border-border bg-muted font-mono text-xs text-muted-foreground`}
>
{label}
</AspectRatio>
))}
</div>
<script setup lang="ts">
import { AspectRatio } from "@/components/ui/aspect-ratio";
</script>
<template>
<div class="flex items-start gap-4">
<AspectRatio
:key="b.label"
:ratio="b.ratio"
:class="`${b.width} flex items-center justify-center rounded-lg border border-border bg-muted font-mono text-xs text-muted-foreground`"
>
{{ b.label }}
</AspectRatio>
</div>
</template>
<script lang="ts">
import { AspectRatio } from "$lib/components/ui/aspect-ratio";
</script>
<div class="flex items-start gap-4">
{#each boxes as b (b.label)}
<AspectRatio
ratio={b.ratio}
class="{b.width} flex items-center justify-center rounded-lg border border-border bg-muted font-mono text-xs text-muted-foreground"
>
{b.label}
</AspectRatio>
{/each}
</div>
registry/ui/aspect-ratio.tsx
import { cn } from "cn";
import type * as React from "react";
function AspectRatio({
ratio,
className,
style,
...props
}: React.ComponentProps<"div"> & { ratio: number }) {
return (
<div
data-slot="aspect-ratio"
style={{ "--ratio": ratio, ...style } as React.CSSProperties}
className={cn("relative aspect-(--ratio)", className)}
{...props}
/>
);
}
export { AspectRatio };
registry/ui/aspect-ratio/AspectRatio.vue
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/registry/edmi/lib/utils'
const props = defineProps<{
ratio: number
class?: HTMLAttributes['class']
}>()
</script>
<template>
<div
data-slot="aspect-ratio"
:style="{ '--ratio': props.ratio }"
:class="cn('relative aspect-(--ratio)', props.class)"
>
<slot />
</div>
</template>
registry/ui/aspect-ratio/index.ts
export { default as AspectRatio } from "./AspectRatio.vue";
src/lib/registry/ui/aspect-ratio/aspect-ratio.svelte
<script lang="ts">
import { cn, type WithElementRef } from "$lib/utils.js";
import type { HTMLAttributes } from "svelte/elements";
let {
ref = $bindable(null),
class: className,
children,
ratio,
style,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & { ratio: number } = $props();
</script>
<div
bind:this={ref}
data-slot="aspect-ratio"
style="--ratio: {ratio};{style ?? ''}"
class={cn("relative aspect-(--ratio)", className)}
{...restProps}
>
{@render children?.()}
</div>
src/lib/registry/ui/aspect-ratio/index.ts
import Root from "./aspect-ratio.svelte";
export { Root, Root as AspectRatio };
Prop Type Default
ratio number required
  • None; same as shadcn.