Aspect ratio
Locks content to a ratio so layouts do not jump while loading.
16 / 9
1 / 1
9 / 16
16 / 9
1 / 1
9 / 16
16 / 9
1 / 1
9 / 16
import { AspectRatio } from "@/components/ui/aspect-ratio";
export default function Demo() { return ( <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";
const boxes = [ { label: "16 / 9", ratio: 16 / 9, width: "w-52" }, { label: "1 / 1", ratio: 1, width: "w-28" }, { label: "9 / 16", ratio: 9 / 16, width: "w-20" },];</script>
<template> <div class="flex items-start gap-4"> <AspectRatio v-for="b in boxes" :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";
const boxes = [ { label: "16 / 9", ratio: 16 / 9, width: "w-52" }, { label: "1 / 1", ratio: 1, width: "w-28" }, { label: "9 / 16", ratio: 9 / 16, width: "w-20" }, ];</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>Installation
Section titled “Installation”npx shadcn@latest add @edmi-ui/aspect-ratiopnpm dlx shadcn@latest add @edmi-ui/aspect-ratioyarn dlx shadcn@latest add @edmi-ui/aspect-ratiobunx shadcn@latest add @edmi-ui/aspect-ratioPick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.
Copy the code from Component source into your project and update the import paths to match your aliases.
npx shadcn-vue@latest add @edmi-ui/aspect-ratiopnpm dlx shadcn-vue@latest add @edmi-ui/aspect-ratioyarn dlx shadcn-vue@latest add @edmi-ui/aspect-ratiobunx shadcn-vue@latest add @edmi-ui/aspect-ratioPick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.
Copy the code from Component source into your project and update the import paths to match your aliases.
npx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/aspect-ratio.jsonpnpm dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/aspect-ratio.jsonyarn dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/aspect-ratio.jsonbunx --bun shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/aspect-ratio.jsonPick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.
Copy the code from Component source into your project and update the import paths to match your aliases.
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>Component source
Section titled “Component source”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 };<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>export { default as AspectRatio } from "./AspectRatio.vue";<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>import Root from "./aspect-ratio.svelte";
export { Root, Root as AspectRatio };| Prop | Type | Default |
|---|---|---|
ratio |
number |
required |
✦ Edmi additions
Section titled “✦ Edmi additions”- None; same as shadcn.