Drivn vs shadcn/ui — Aspect Ratio Component Compared
Side-by-side comparison of Drivn and shadcn/ui React Aspect Ratio components — runtime deps, native CSS, API shape, ratio presets, and default behavior.
Drivn's AspectRatio and shadcn/ui's AspectRatio look the same at the call site — both lock a piece of content to a fixed width-to-height ratio. How they arrive at the same behavior is where they diverge. shadcn's version is a styled wrapper around @radix-ui/react-aspect-ratio, a Radix UI primitive that handles forwardRef, ratio math, and a historical padding-bottom fallback for older browsers. Drivn's version writes the ratio directly to an inline style and lets the browser handle the rest.
On evergreen browsers, both components render identically. What differs is the dependency graph behind each one, the shape of the prop that controls the ratio, and whether 16/9 is a default the component ships with or something you retype on every usage. Drivn accepts a string preset ("16/9", "4/3", "1/1") or a raw number; shadcn accepts a number only. Drivn defaults to "16/9" when the prop is omitted; shadcn requires the ratio on every instance.
This comparison walks through runtime dependencies, the ratio prop API, default behavior, the container model for children, and what happens in older browsers that predate the native aspect-ratio CSS property. Every section shows real code from both libraries so the decision is based on what ships to your users, not on a tagline.
Side-by-side comparison
| Feature | Drivn | shadcn/ui |
|---|---|---|
| Runtime UI dependencies | None (React + Tailwind) | @radix-ui/react-aspect-ratio primitive |
| Ratio prop type | "16/9" | "4/3" | "1/1" | number | number |
| Default ratio | "16/9" | None (required on every instance) |
| String presets | ||
| Implementation | Inline style + native CSS aspect-ratio | Radix primitive via forwardRef |
| Container classes | relative w-full overflow-hidden | None by default |
| Absolute-child overlays | Ready (relative by default) | Needs extra wrapper |
| Source size | ≈15 lines, no primitive | Wrapper + Radix primitive |
| License | MIT | MIT |
| Copy-paste install |
API side-by-side
shadcn/ui exports AspectRatio from @/components/ui/aspect-ratio, a thin forwardRef wrapper around the Radix UI primitive at @radix-ui/react-aspect-ratio. You pass a ratio prop as a numeric expression — typically 16 / 9 or 4 / 3 — and any children render inside the ratio-locked container. Drivn exports the same name from the same path, but the file behind it is a single React function component with no forwardRef and no primitive import. The aspect ratio docs show the full API and props table.
Both libraries accept the same shape at the call site — <AspectRatio ratio={...}><img /></AspectRatio> — so migration in either direction is largely a find-and-replace on the import path. What diverges is the behavior when the ratio prop is omitted, the accepted type of that prop, and the dependency graph each component drags along at install time.
1 // shadcn/ui — wraps Radix primitive, numeric ratio 2 import { AspectRatio } from '@/components/ui/aspect-ratio' 3 4 <AspectRatio ratio={16 / 9}> 5 <img src="/hero.jpg" alt="Hero" className="h-full w-full object-cover" /> 6 </AspectRatio> 7 8 // Drivn — no runtime deps, string preset or number 9 import { AspectRatio } from '@/components/ui/aspect-ratio' 10 11 <AspectRatio ratio="16/9"> 12 <img src="/hero.jpg" alt="Hero" className="w-full h-full object-cover" /> 13 </AspectRatio>
Runtime dependencies
shadcn/ui's AspectRatio depends on @radix-ui/react-aspect-ratio, a Radix UI primitive that adds roughly two kilobytes gzipped on top of React once included. The primitive itself is small and well-maintained, but it arrives through the wider Radix dependency graph that also pulls in @radix-ui/react-primitive and a handful of shared utility packages used across every other Radix component you might have installed.
Drivn's AspectRatio depends on nothing outside of React and your existing Tailwind setup. The whole component file is fifteen lines — an interface declaration, a single function body, and an inline style that writes the aspect-ratio CSS property directly. No primitive, no forwardRef, no ref polyfill. If you open the component file after running the Drivn CLI, the source reads top to bottom without any framework abstraction. For a team that audits every runtime dependency, the difference is one fewer package in package.json and one fewer version bump to track.
The ratio prop API
shadcn/ui's ratio prop is typed as number, so you pass an arithmetic expression at every call site — ratio={16 / 9}, ratio={4 / 3}, or ratio={1} for a square. The expression is readable once and becomes repetitive noise when echoed across a media gallery, a video grid, or a list of thumbnail cards. There is no default; leave the prop off and you get a container with no enforced ratio at all.
Drivn's ratio prop accepts either a string preset ("16/9", "4/3", "1/1") or a raw number for non-standard ratios such as 2.35 for cinemascope. The preset form is a string literal union, so TypeScript autocompletes the three common ratios at every call site, and the component falls back to "16/9" if you omit the prop entirely. The numeric form is still available when you need a custom ratio — the React AspectRatio examples show both forms in context.
Neither API is objectively better. The numeric shape matches how designers think about ratios in Figma; the string preset matches how the underlying CSS aspect-ratio value actually reads in browser devtools. Pick the shape your team already uses in design specs.
1 // shadcn/ui — always a number, no default 2 <AspectRatio ratio={16 / 9}>{content}</AspectRatio> 3 <AspectRatio ratio={4 / 3}>{content}</AspectRatio> 4 <AspectRatio ratio={1}>{content}</AspectRatio> 5 6 // Drivn — string preset (defaults to "16/9"), or custom number 7 <AspectRatio>{content}</AspectRatio> 8 <AspectRatio ratio="4/3">{content}</AspectRatio> 9 <AspectRatio ratio="1/1">{content}</AspectRatio> 10 <AspectRatio ratio={2.35}>{content}</AspectRatio>
Container model and children
Both libraries drop their children inside a block-level container that enforces the target ratio via the native CSS aspect-ratio property. Children render in normal flow and are typically sized to fill the container with w-full h-full object-cover when the child is an image. For iframes — a YouTube embed, a Vimeo player, a Google Maps panel — the same fill pattern works because iframes respect explicit dimensions reliably across engines.
Drivn also adds relative and overflow-hidden to the container at install time. The relative anchor lets absolutely-positioned children (captions, play-button overlays, gradient hovers) sit inside the ratio box without an extra wrapper. The overflow-hidden keeps oversized content — a Ken Burns zoom, a scaled-up image hover — clipped to the box edge. shadcn's wrapper does not set either class by default, so overlay patterns need their own positioning wrapper on top. For a responsive hero section with text on media, Drivn removes one layer of wrapper JSX.
Browser support and legacy engines
Both components lean on the native CSS aspect-ratio property, supported across every evergreen browser and roughly 94% of global traffic in 2026 per caniuse.com. For any product whose audience runs Chrome, Safari, Firefox, Edge, or their mobile counterparts from the last four years, either library works with zero fallback considerations at all.
Historically, Radix's aspect-ratio primitive shipped a padding-bottom percentage fallback for browsers that predated the native property. Modern @radix-ui/react-aspect-ratio has simplified to use the native property directly, so shadcn's behavior matches Drivn's on today's engines. Neither library gives you a polyfill for browsers from before 2022 — Internet Explorer 11 or early Android WebViews on legacy devices — out of the box.
Because Drivn's component lives in your repo after the CLI install, adding a padding-bottom fallback for a specific legacy audience is a five-line edit inside src/components/ui/aspect-ratio.tsx. That kind of surgical tweak is harder with shadcn because the fallback logic, if it returned, would need to be patched inside the Radix primitive.
Install Drivn in one command
Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.
npx drivn@latest createRequires Node 18+. Works with npm, pnpm, and yarn.
Frequently asked questions
Migrate if you want to drop the @radix-ui/react-aspect-ratio package from your dependency tree, prefer a default ratio baked into the component, or want the convenience of string presets like "16/9" instead of arithmetic expressions at every call site. Stay on shadcn if you already use several Radix primitives and prefer one consistent wrapper style across the library, or if your team finds ratio={16 / 9} more explicit at the call site. The rendered output is identical on 2026 browsers, so the choice is about API taste and dependency footprint rather than visual behavior.
The native aspect-ratio CSS property covers roughly 94% of global traffic in 2026 — all modern Chrome, Safari, Firefox, and Edge builds. If your audience includes Internet Explorer 11 or legacy Android WebViews, neither Drivn nor shadcn ships a polyfill in the default install. You would add a padding-bottom percentage fallback by editing the component file after install — five additional lines inside src/components/ui/aspect-ratio.tsx — and because the source lives in your repo, the change survives every future update.
Pass a raw number to the ratio prop — ratio={21 / 9} or the equivalent 2.33. The string preset form only covers the three most common ratios ("16/9", "4/3", "1/1") because a union with every imaginable ratio would pollute the autocomplete surface. For cinemascope (2.35), ultrawide (21 / 9), or portrait video (9 / 16), the numeric form is the right fit and TypeScript will not complain because number is part of the prop's union type.
Yes. Drivn's container ships with relative and overflow-hidden Tailwind classes baked in, so any child with position: absolute anchors to the ratio box automatically. A typical pattern is an image as the first child with w-full h-full object-cover, followed by an overlay div positioned absolutely at the bottom with padding and a gradient background. shadcn's wrapper does not set relative by default, so the equivalent layout needs an extra wrapper div or a custom className on every instance.
Yes. Render <Image fill /> as the child and it fills the ratio-locked container automatically. The parent's native aspect-ratio CSS gives fill its box dimensions without any extra wrapper, so the pattern is a two-element stack — AspectRatio on the outside, Image fill on the inside. Set sizes on the Image for correct responsive srcset handling. The same two-element pattern also works with the shadcn version once you pass a numeric ratio prop.