Skip to main content

How do you write ratios in the aspect-ratio property?

When you define an aspect ratio as x/y, you can only use numbers for x and y.

I’ve been using the aspect-ratio CSS property, and I often use it with --width and --height properties that I define based on the dimensions of the image I’m displayed, but I’ve been a bit confused about when I need to use calc() to compute the ratio.

You can define aspect-ratio as a ratio of two numbers

I want to be able to define a --width and --height property, and calculate the aspect ratio in CSS. For example:

img {
  --width: 1600;
  --height: 900;
  aspect-ratio: var(--width) / var(--height);         /* ✅ */
}

This works, because aspect-ratio can take a <ratio> data type, which is two numbers separated by a slash, or a single number with no slash.

Examples are 16/9, 4/3, or 1.5. And here’s the important bit: you can only have a ratio of two numbers.

You can’t define aspect-ratio as a ratio of two dimensions

Sometimes I write my --width and --height properties with units, because I’m going to use them with units elsewhere. Then I’d write something like:

img {
  --width: 1600px;
  --height: 900px;
  aspect-ratio: var(--width) / var(--height);         /* ❌ */
}

This doesn’t work, because it’s a ratio of two dimensions, not two numbers.

Now I write this TIL, I think I probably shouldn’t be adding units to these properties – it makes them more unwieldy to use later.

You can calc() to get a ratio of two dimensions… sometimes

Here’s a clever idea I had: what if I pass my ratio to the calc() function to get a number?

img {
  --width: 1600px;
  --height: 900px;
  aspect-ratio: calc(var(--width) / var(--height));  /* ⚠️ */
}

The units cancel out, and I should be left with a nuber.

This works… sometimes.

In Safari 18.2 on my work laptop, this gets me a numeric aspect ratio. In Safari 18.1 on my home computer, this rule is ignored and I get aspect-ratio: auto. Why are they different?

I looked in the Safari 18.2 Release Notes, and I found this item:

Updated calc() to the most recent web standard, including support for dividing by numbers with additional units. (134446246)

And this is why I’ve found this whole affair so confusing – I’ve been working in browsers that look the same but have subtly different behaviour, so I “learn” what works on one and then that knowledge falls over when I go to the other.

What I’ll do from now on

I’ll define my --width and --height properties as numbers, without dimensions. When I need to add a dimension, I can do that with calc():

width: calc(var(--width) * 1px);

I’ll define my aspect-ratio as a ratio of those two numbers, without wrapping it in calc() or getting units involved.