React Aspect Ratio Examples — Video, Image, Portrait
Copy-paste React Aspect Ratio examples — 16:9 video embed, responsive hero image, square avatar tile, portrait video clip, and Next.js Image integration.
Aspect ratio is the kind of CSS problem that reads as solved in a mockup and turns fiddly the moment real media loads. A container has to hold its shape whether the child is a 1920x1080 still, a YouTube iframe, a slow-loading hero, or a Next.js Image with fill. Get it wrong and the page jumps every time a picture finishes downloading, the crop shifts on mobile, or an overlay caption drifts a line away from where the designer pinned it in Figma.
Drivn's AspectRatio is deliberately small — a single div that takes a ratio prop and writes it straight to the native aspect-ratio CSS property. The prop accepts a string preset ("16/9", "4/3", "1/1") or any raw number like 2.35, and it defaults to "16/9" so hero images and video embeds need no prop at all. The wrapper carries relative w-full overflow-hidden, which means absolutely-positioned overlays anchor to the ratio box on their own and any oversized child is clipped cleanly at the edge.
This page collects five patterns you will actually ship: a default 16:9 video container, a responsive hero image, a square avatar tile, a portrait 9:16 reel clip, and the two-line Next.js Image fill integration. Every snippet is copy-paste and assumes Drivn is already installed via the CLI. For the engineering trade-offs against shadcn/ui's AspectRatio, see Drivn vs shadcn/ui AspectRatio.
Default 16:9 video embed
The single most common AspectRatio use is a 16:9 container for an embedded video — YouTube, Vimeo, Loom, Wistia, or a self-hosted <video> element. Drivn's default ratio is "16/9", so you can omit the prop entirely for this case. Children fill the container with w-full h-full, and the overflow-hidden default keeps any slight oversizing clipped cleanly to the ratio box edge.
Drop this snippet into a marketing page, a course lesson, or a product landing hero. Because the ratio is locked at 16:9, the iframe never triggers cumulative layout shift when it loads — the space is reserved by CSS before any JavaScript runs. The aspect ratio docs cover the full prop list and API reference.
1 import { AspectRatio } from '@/components/ui/aspect-ratio' 2 3 // Default ratio is "16/9" — the prop is optional 4 <AspectRatio> 5 <iframe 6 src="https://www.youtube.com/embed/dQw4w9WgXcQ" 7 title="YouTube video" 8 className="w-full h-full" 9 allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" 10 allowFullScreen 11 /> 12 </AspectRatio>
Responsive hero image
For a hero banner or landing-page image, pair AspectRatio with a single <img> styled w-full h-full object-cover. The object-cover rule ensures the image fills the ratio box and crops the overflow rather than distorting the pixels. Add rounded-lg or rounded-2xl on either the container or the child for rounded media cards that match your card component radius.
This pattern also works for responsive product images on e-commerce grids. Pair the 16/9 ratio with a max-width on the parent container and the image scales fluidly down to mobile without ever changing shape. The browser serves the right resolution through a srcset on the img tag if you configure one — nothing about AspectRatio is specific to srcset handling, so the usual HTML rules apply.
For a more advanced setup that layers a gradient and text overlay on top of the image, the container is already position: relative, so overlays anchor inside the ratio box without an extra wrapper div.
1 <AspectRatio ratio="16/9"> 2 <img 3 src="/hero.jpg" 4 alt="Team collaborating" 5 className="w-full h-full object-cover rounded-lg" 6 /> 7 </AspectRatio>
Square 1:1 avatar tile
Square tiles are everywhere once you start looking: profile galleries, team pages, product thumbnails, album artwork, Instagram-style grids. Reach for the "1/1" string preset — one of the three built-ins next to "16/9" and "4/3" — and drop each tile into a Tailwind grid so the layout stays square at every breakpoint. Inside each box the image renders w-full h-full object-cover, so cropping stays uniform no matter how the source photos were exported.
When the square specifically holds a user's face, Drivn's dedicated Avatar component is the better fit — it bundles rounded fallbacks, image loading states, and fixed size presets. Keep AspectRatio for square media that is not a person: catalog thumbnails, blog card covers, collection tiles, cover art. At runtime the DOM is the same single div either way; the choice is about signalling intent to the next developer who reads the code, not about visual output.
1 <div className="grid grid-cols-2 md:grid-cols-4 gap-4"> 2 {images.map((img) => ( 3 <AspectRatio key={img.id} ratio="1/1"> 4 <img 5 src={img.url} 6 alt={img.alt} 7 className="w-full h-full object-cover rounded-lg" 8 /> 9 </AspectRatio> 10 ))} 11 </div>
Portrait 9:16 reel clip
Vertical video is now the default shape for short-form content — TikTok, Instagram Reels, YouTube Shorts, and Spotify Video all render at 9:16. AspectRatio handles this with a custom numeric ratio of 9 / 16, which resolves to 0.5625. You pass the division expression directly or the evaluated number, whichever reads better in the surrounding code.
Constrain the parent container to a maximum width around 320-400 pixels for a natural mobile-preview feel on desktop. Without the constraint, a 9:16 box becomes taller than most viewports and pushes subsequent page content far below the fold. The parent should also avoid overflow: hidden at the section level if you want the embedded player's fullscreen controls to escape the ratio box on user interaction.
For a gallery of reel clips, combine this ratio with a horizontal scroll container. The ScrollArea component gives you styled native scrollbars and snap-scrolling behavior without a third-party dependency.
1 <div className="max-w-sm"> 2 <AspectRatio ratio={9 / 16}> 3 <video 4 src="/reel.mp4" 5 className="w-full h-full object-cover rounded-xl" 6 controls 7 playsInline 8 /> 9 </AspectRatio> 10 </div>
Next.js Image with fill
Next.js's Image component gives you automatic srcset generation, blurhash placeholders, and lazy loading. Render it with the fill prop as a child of AspectRatio and the framework handles all the responsive sizing details. Set sizes to help Next.js pick the right resolution at each viewport width — a typical value for a hero image is "(max-width: 768px) 100vw, 50vw".
Because AspectRatio provides a container with explicit dimensions through the native aspect-ratio property, Image fill has a concrete box to fill. This pattern avoids the older trick of wrapping the image in a relative div with a padding-bottom hack; the ratio is enforced by CSS rather than by layout math. The rendered HTML stays minimal — two nested wrappers and the Next.js-generated <img> with its srcset.
See the Installation guide for how to set up next/image with Drivn, and the theming docs for how media cards in light and dark mode should tune their background placeholder colors before the image loads.
1 import Image from 'next/image' 2 import { AspectRatio } from '@/components/ui/aspect-ratio' 3 4 <AspectRatio ratio="16/9"> 5 <Image 6 src="/hero.jpg" 7 alt="Hero" 8 fill 9 sizes="(max-width: 768px) 100vw, 50vw" 10 className="object-cover rounded-lg" 11 /> 12 </AspectRatio>
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
The default is "16/9", set as the default value of the ratio prop inside src/components/ui/aspect-ratio.tsx. Change it by editing the default in the destructured prop signature — for instance to ratio = "4/3". Because the component file lives in your repo after install, the change is permanent and survives every future package update. Most teams keep the "16/9" default and override per call site when needed.
Functionally they are identical — AspectRatio writes the same aspect-ratio property to the container via inline style. The component exists to give you a consistent, typed API across your codebase, so every ratio-locked media box uses the same wrapper rather than scattered one-off class names. It also bakes in position: relative and overflow: hidden defaults that media containers usually want anyway.
Yes. The container is a block-level div with w-full, so it expands to fill the available width of its flex parent and then calculates height from the ratio. If the flex parent has align-items: stretch on a row layout, the AspectRatio will not grow vertically beyond its computed ratio. In a column layout with flex-grow set on a sibling, the AspectRatio stays at its ratio-derived height naturally.
Yes. A common pattern is an outer AspectRatio for a card tile with an inner AspectRatio for the card's thumbnail at a different ratio — for example a 4:3 card containing a 16:9 thumbnail above a title block. Each level has its own ratio prop and resolves independently. There is no performance cost to nesting; every instance is a single div with one inline style and three Tailwind utility classes.
Yes. The ratio is enforced by the aspect-ratio CSS property on the container, not by the children's intrinsic size. An empty AspectRatio still reserves its ratio-correct box, which is why the pattern works for skeleton loading states — render an empty container with a bg-muted class while the real content fetches, and the layout stays stable the moment the image or video slots in.

