Summit Themes
Blog

How to Use aspect-ratio in Tailwind CSS - Complete v4 Guide

Before the CSS aspect-ratio property existed, locking an element to a specific width-to-height ratio meant padding hacks, absolutely-positioned children, and a silent prayer that nothing broke on Safari. Today the property is universally supported, and Tailwind CSS v4 ships a clean set of utilities that map directly to it. This guide covers every syntax form — built-ins, arbitrary values, CSS variable shorthand, and the v4-specific @theme approach for custom tokens — so you know exactly which tool to reach for and why.

Everything here targets Tailwind CSS v4 (CSS-first configuration, no tailwind.config.js). If you are still on v3, the built-in classes work the same way, but the customization story is different: v3 uses extend.aspectRatio in your JS config file rather than @theme.

The built-in aspect-ratio utilities

Tailwind v4 ships four ready-to-use classes that cover the most common cases:

  • aspect-square — sets aspect-ratio: 1 / 1. Useful for avatars, icon containers, and thumbnail grids.
  • aspect-video — sets aspect-ratio: var(--aspect-video), which resolves to 16 / 9. The right pick for embedded iframes and video backgrounds.
  • aspect-auto — sets aspect-ratio: auto, restoring the browser's default (intrinsic ratio for replaced elements like <img>, no ratio constraint for others).
  • aspect-<ratio> — any slash-separated fraction you type becomes a class. aspect-3/2, aspect-4/3, aspect-9/16 (portrait video) all work out of the box.
<!-- 16:9 YouTube embed -->
<iframe
  class="aspect-video w-full rounded-lg"
  src="https://www.youtube.com/embed/dQw4w9WgXcQ"
  allowfullscreen
></iframe>

<!-- Square avatar -->
<img
  class="aspect-square w-16 rounded-full object-cover"
  src="/avatar.jpg"
  alt="Profile photo"
/>

<!-- Classic photo ratio -->
<img
  class="aspect-3/2 w-full object-cover"
  src="/hero.jpg"
  alt="Hero image"
/>

The aspect-<ratio> pattern (e.g. aspect-3/2) is new in Tailwind v4. In v3, only aspect-square and aspect-video were built in — everything else required arbitrary values or a config entry. In v4 the fraction syntax is parsed directly, so you get a much wider set of classes without writing a line of configuration.

Arbitrary values with square brackets

When the built-in fraction syntax is not enough — for example, when you need a calculated or unusual ratio — use the arbitrary-value syntax with square brackets:

<!-- Unusual fixed ratio -->
<div class="aspect-[7/4] overflow-hidden rounded-xl">
  <img class="h-full w-full object-cover" src="/banner.jpg" alt="" />
</div>

<!-- Calc expression -->
<div class="aspect-[calc(16*1.5)/9]">
  ...
</div>

Anything you can write as a valid CSS aspect-ratio value goes inside the brackets. Tailwind applies it directly without any escaping gymnastics on your part, though you should avoid spaces inside the brackets (use underscores if needed, e.g. aspect-[4_/_3], though a plain slash works fine without spaces).

CSS variable shorthand: aspect-(…)

Tailwind v4 introduced a parentheses shorthand for CSS custom properties. Instead of writing aspect-[var(--my-ratio)], you write aspect-(--my-ratio). Tailwind wraps the property name in var() automatically:

<!-- Both lines produce identical output -->
<div class="aspect-[var(--card-ratio)]">...</div>
<div class="aspect-(--card-ratio)">...</div>

This shorthand is useful when the ratio is set dynamically via JavaScript or from a parent component, because the CSS variable can change at runtime and the element tracks it without any class swapping:

<div
  style="--card-ratio: 4 / 3"
  class="aspect-(--card-ratio) overflow-hidden"
>
  <img class="h-full w-full object-cover" src="/photo.jpg" alt="" />
</div>

Defining custom aspect-ratio tokens with @theme

In Tailwind v4, design tokens live in your CSS file inside an @theme block — there is no JavaScript config file. Custom aspect ratio tokens follow the --aspect-* namespace. Once defined, Tailwind generates a matching utility class automatically.

/* app.css (or whichever file holds your @tailwind imports) */
@import "tailwindcss";

@theme {
  --aspect-retro: 4 / 3;
  --aspect-portrait: 3 / 4;
  --aspect-cinema: 21 / 9;
  --aspect-tall: 9 / 16;
}

After that, the classes aspect-retro, aspect-portrait, aspect-cinema, and aspect-tall are available everywhere in your project, just like aspect-video:

<!-- Cinema-scope hero banner -->
<div class="aspect-cinema w-full overflow-hidden">
  <img class="h-full w-full object-cover" src="/banner.jpg" alt="" />
</div>

<!-- Portrait card for mobile-first layouts -->
<div class="aspect-portrait overflow-hidden rounded-2xl">
  <img class="h-full w-full object-cover" src="/card.jpg" alt="" />
</div>

The token also becomes a native CSS custom property on :root, so you can reference it in plain CSS as well: aspect-ratio: var(--aspect-retro). No build step needed to use it — it flows through the cascade like any other CSS variable.

Responsive aspect ratios

Combine aspect-ratio utilities with Tailwind's breakpoint prefixes to change the ratio at different viewport sizes. A common pattern is landscape on desktop, square on mobile:

<img
  class="aspect-square md:aspect-3/2 w-full object-cover rounded-xl"
  src="/team.jpg"
  alt="Team photo"
/>

The same technique handles vertical video vs. horizontal at a breakpoint:

<!-- Tall portrait on mobile, 16:9 on wider screens -->
<iframe
  class="aspect-tall sm:aspect-video w-full"
  src="https://www.youtube.com/embed/dQw4w9WgXcQ"
  allowfullscreen
></iframe>

Where aspect-tall is a custom 9 / 16 token defined in @theme as shown above.

Pairing aspect-ratio with object-fit

Setting an aspect ratio on an <img> or <video> constrains the box but does not by itself control how the media fills that box. Always pair aspect-ratio with an object-* utility:

  • object-cover — fills the box, crops the overflow. Best for hero images and cards where you want full coverage.
  • object-contain — fits the media inside the box, leaving letterboxing. Best for logos and product shots where nothing should be cropped.
  • object-fill — stretches to fill the box exactly. Rarely what you want for photos, but useful for certain SVG illustrations.
  • object-position-* (e.g., object-top, object-center) — controls which part of the media shows when cropping.
<!-- Card thumbnail: fill and crop to focus point -->
<div class="aspect-3/2 overflow-hidden rounded-lg">
  <img
    class="h-full w-full object-cover object-top"
    src="/blog-cover.jpg"
    alt=""
  />
</div>

<!-- Logo: contain, never crop -->
<div class="aspect-square flex items-center justify-center bg-gray-50 p-4">
  <img
    class="h-full w-full object-contain"
    src="/client-logo.svg"
    alt="Client logo"
  />
</div>

A practical image grid example

Here is a small responsive image grid that uses aspect-ratio to keep all cards the same height regardless of the source image's intrinsic dimensions:

<ul class="grid grid-cols-2 gap-4 md:grid-cols-3">
  <li class="aspect-square overflow-hidden rounded-xl">
    <img class="h-full w-full object-cover" src="/work-1.jpg" alt="Project 1" />
  </li>
  <li class="aspect-square overflow-hidden rounded-xl">
    <img class="h-full w-full object-cover" src="/work-2.jpg" alt="Project 2" />
  </li>
  <li class="aspect-square overflow-hidden rounded-xl">
    <img class="h-full w-full object-cover" src="/work-3.jpg" alt="Project 3" />
  </li>
</ul>

Without aspect-square, the grid rows shift whenever an image's natural height differs from the others. With it, every card is locked to 1:1 and the layout is stable regardless of what images you drop in.

Quick reference: all the syntax forms

  • aspect-square — 1:1, built in.
  • aspect-video — 16:9, built in.
  • aspect-auto — removes any ratio constraint.
  • aspect-3/2 (or any N/M) — fraction parsed directly; no config needed in v4.
  • aspect-[value] — arbitrary CSS value, including calc() expressions.
  • aspect-(--custom-property) — shorthand for aspect-[var(--custom-property)].
  • @theme { --aspect-name: W / H; } — registers a custom token and generates the aspect-name class.

Conclusion

The aspect-ratio utilities in Tailwind v4 are a significant step up from v3. The fraction syntax (aspect-3/2) removes most of the need for arbitrary values in day-to-day work, the CSS-variable shorthand keeps dynamic ratios clean, and the @theme block gives you a proper design-token workflow for any ratio your project uses repeatedly. Pair whichever variant fits your situation with object-cover or object-contain, and responsive image layouts stop being a source of layout surprises.