Display
Aspect Ratio.
Keeps media and placeholders at a fixed width to height ratio as the container resizes.
Screenshot16 : 9
import { Castle } from "lucide-react";
import { AspectRatio } from "@/components/ui/aspect-ratio";
export default function AspectRatioDemo() {
return (
<div className="w-full max-w-md">
<AspectRatio ratio={16 / 9} className="overflow-hidden rounded-lg border bg-accent bg-grid shadow-block-sm">
<div className="flex size-full items-center justify-center text-[#b7ca9e]">
<Castle className="size-14 stroke-[1.25]" />
</div>
<span className="absolute top-3 left-4 font-mono text-[9px] tracking-[0.2em] text-[#b7ca9e] uppercase">
Screenshot
</span>
<span className="absolute right-4 bottom-3 font-mono text-[9px] tracking-[0.2em] text-[#b7ca9e]/70 uppercase">
16 : 9
</span>
</AspectRatio>
</div>
);
}Installation#
With the CLI
$npx lanterncn add aspect-ratioThis also installs the Lantern theme and any Lantern UI components it depends on. The shadcn CLI works directly too: npx shadcn@latest add httptim/lantern-ui/aspect-ratio. See Installation if your project is not set up yet.
Manually
Install the dependencies
npm install radix-uiCopy the source into your project
components/ui/aspect-ratio.tsx"use client"; import * as React from "react"; import { AspectRatio as AspectRatioPrimitive } from "radix-ui"; function AspectRatio({ ...props }: React.ComponentProps<typeof AspectRatioPrimitive.Root>) { return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} />; } export { AspectRatio };Update the import paths to match your project
The source imports
cnfrom@/lib/utils.
Usage#
import { AspectRatio } from "@/components/ui/aspect-ratio";<AspectRatio ratio={16 / 9} className="rounded-lg border bg-accent bg-grid">
<img src="/screenshot.png" alt="Turtle Farm" className="size-full object-cover" />
</AspectRatio>The child fills the box absolutely, so give images size-full and object-cover. Put rounded corners and overflow-hidden on AspectRatio itself.
Examples#
Other ratios
1 : 1
4 : 3
3 : 4
import { Box, Map, Pickaxe } from "lucide-react";
import { AspectRatio } from "@/components/ui/aspect-ratio";
const tiles = [
{ ratio: 1, label: "1 : 1", icon: Box },
{ ratio: 4 / 3, label: "4 : 3", icon: Map },
{ ratio: 3 / 4, label: "3 : 4", icon: Pickaxe },
];
export default function AspectRatioSquare() {
return (
<div className="grid w-full max-w-md grid-cols-3 items-start gap-3">
{tiles.map(({ ratio, label, icon: Icon }) => (
<AspectRatio key={label} ratio={ratio} className="overflow-hidden rounded-md border bg-accent bg-grid">
<div className="flex size-full flex-col items-center justify-center gap-2 text-[#b7ca9e]">
<Icon className="size-6 stroke-[1.5]" />
<span className="font-mono text-[9px] tracking-[0.2em] uppercase">{label}</span>
</div>
</AspectRatio>
))}
</div>
);
}