Aspect ratio: no need for container units!
Tags: css, html, webdev, todayilearned
Published: 2021-12-29 08:31:56

When I first heard about [container queries](https://css-tricks.com/a-cornucopia-of-container-queries/), I was mistaken that there would be **"container units"** in CSS, probably a unit like percent, but relative to the other axis. "100cw" would always be 100% of the container width, even if used insight a `height` property.

## Trying to make Sense of a Misconception 🤔🤓🤣

I tried to make sense of the hype. Container units could possibly a handy feature. I even had an actual use case in a customer project this year.

**Disclaimer**: there will be no container units in CSS in the near future (and probably never), because we probably don't need them. At least there have been [alternatives](#aspect-ratio-as-an-elegant-alternative) for every of my use cases so far.

---

Let's have a look at my recent use case:

### A Carousel Slideshow inside a Column 🎠🎪

This is an actual requirement I had in 2021. While I would rarely recommend using slideshow carousels at all, this is just my personal opinion as a front-end developer. I am no usability expert, and some of my customer (or rather the teams coming up with the designs) seem to love anything that moves on a website.

Let's just imagine we want to style a slideshow.

### Dynamic Height Calculation relative to Container Width

The slideshow container is a block element that needs to keep its proportions without stretching or clipping its content, by setting the height in proportion to the width. Just like HTML image elements behave in the regular document flow.

```html
<img width="800" height="600" alt="an image" src="img.jpg">

<style>
img {
  max-width: 100%;
  height: auto;
}
</style>
```

Unless they are taken out of the flow by using `position: absolute` or a CSS transformation, which is a typical side effect of a slideshow / carousel. Have a look at this simplified code example:

```html
<div class="canvas">
  <img width="800" height="600" alt src="img.jpg" class="active">
  <img width="800" height="600" alt src="img2.jpg">
</div>

<style>
.canvas {
  position: relative;
}

img {
  position: absolute;
  max-width: 100%;
  height: auto;
}

image:not(.active) {
  display: none;
}

</style>
```

This is a very basic abstraction of a slideshow markup. A series of images, usually only one of them (the "active" image) visible at a time, while the others will be revealed by scrolling, dragging, swiping or waiting for an automated animation.

But this example is enough to reproduce a typical challenge that web developers face when [dealing with absolutely positioned content](http://tympanus.net/codrops/css_reference/position/).

### Relatively absolute Loss of Height

[![Codepen screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gfotf7ikzvatc5iu1k8j.png)](https://codepen.io/openmindculture/pen/gOGoZJW)

[This codepen](https://codepen.io/openmindculture/pen/gOGoZJW) shows how our image container has lost its height instead of growing to the height of the images inside.

Out of the flow, our images now behave like butterflies fyling over the content which they used to be a part of.

🐛 ➤➤➤ 🦋✨ ➤➤➤ 🎠🎪

This is good for the images (because we are free to move and position them anywhere, which is necessary for the desired slideshow effect), but it' bad for our document. The content below our image container now overlaps our slideshow, while it should stay visually below like it did before.

🚧 🚧 🚧 🚧 🚧

### Keeping the Distance

We can set a minimal height, but as the images are dynamically sized (they will shrink when the window is resized to prevent being cut off on small screens like on a mobile device), we can't use a static pixel value here.

### Adapting to the Viewport Width

As long as we only consider the viewport width, we could use viewport units inside a calculation. "Viewport" is the part of the browser that displays our current document. `100vw` means 100% of the available viewport width. This is a simple rule of three calculation:

```css
.canvas {
  min-height: calc(800 / 600 * 100vw);
```

Did this fix our problem?

[![Codepen: Regained Height thanks to the Rule of Three](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vos4miz3rpg7r4if1ye5.png)](https://codepen.io/openmindculture/pen/bGoazdv)

Now we have a height that behaves mostly as expected. We should to fix the additional space below the image, probably due to some unintended inline display behavior or whatever. But the basic concept does its job.

Unless we want to adapt to a parent container.

### Responsive Design inside Container Elements

Maybe our slideshow will be placed inside a column next to a navigation or some ad banners, so we must not rely on the `100vw` viewport width.

Let's just use percentage then, right? No!

While `100vw` is always 100% of the viewport width (don't care about the scrollbar details either), `100%` is always 100% or the current axis, so

`width: 100vw` and `width: 100%` are the same on a top level, but `height: 100vw` vs. `height: 100%` are totally different, as these 100% will be 100% of the height, not of the width!

### Container Units? 📊📐

One might conclude, that we need container units, similar to the viewport units, for our use case, like:

![Screenshot with imaginary container units](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zq3fkeeopoc4boayyy2e.png)

This is no valid CSS (and will probably never be):

```css
.canvas {
  position: relative;
  height: 100cw; // this is NO VALID CSS !!!
  min-height: calc(600 / 800 * 100cw);
```

I just made up this pseudo-code. Don't copy!
There is a better alternative!

## Aspect Ratio as an elegant Alternative

A more elegant alternative to [set a div height from its width](https://stackoverflow.com/questions/70438272/set-a-div-height-from-its-width-and-vice-versa/) is the `aspect-ratio` property.

Why is this elegant? We don't need to define calculations. Instead, we write compact code, that is easy to use and understand. Let's leave it to the browsers to do the proper math, just like they have been handling images properly for decades.

[Aspect ratio](https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio) makes any block element behave just like an image, so we can use it to adapt its width to the viewport and keep its ratio to figure out the appropriate height:

```css
.canvas {
  position: relative;
  aspect-ratio: 800 / 600;
  max-width: 100%
  height: auto;
```

We still have one problem here: max width should be restricted both to the viewport or parent container width and to the image width.

The code example above will make our `.canvas` div too large when the container is wider than the image width:

![The canvas is too large in this example.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v87mzlbpf4a9qveh6sty.png)

We have to set our container `width` to the same width as that of our image element to make it work.

[![Working codepen screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/clqmhg3zvbppzrej0k4k.png)](https://codepen.io/openmindculture/pen/vYepbWJ)

This will resize properly...

![Screenshot of the same codepen in a smaller viewport](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xzi9ik4avtj6bgd4qcbo.png)

... and it should also work inside of a column, when the parent container width is not the full viewport width. That's the use case I described at the beginning of this article.

[![Codepen: CodePen Home
Aspect Ratio inside a Column Container
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o4xykl66qaqoll0zym99.png)](https://codepen.io/openmindculture/pen/PoJEVyB)

## Can I use aspect-ratio?

[![caniuse.com/?search=aspect-ratio](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b0oq06bai8pcn3cp0rvf.png)](https://caniuse.com/?search=aspect-ratio)

The CSS property `aspect-ratio` has fairly good browser support. You could still use the min-height calculation as a fallback for unsupported browsers.

## Conclusion

**There is no need for container units.**

What we do need for better responsive frontend web development are **container queries**, one the most popular missing CSS language feature [according to the state of CSS survey 2021](https://2021.stateofcss.com/en-US/opinions/).

[![missing from css: container queries, parent selector, browser support, nesting. Screenshot from the 2021 state of CSS survey](https://res.cloudinary.com/practicaldev/image/fetch/s--Gxm1vcCZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q14f3xl4cs03t6v77gg8.png)](https://2021.stateofcss.com/en-US/opinions/)

This [cornucopia of container queries by CSS tricks](https://css-tricks.com/a-cornucopia-of-container-queries/) is a good way to understand the upcoming update which can [already be tested after setting a feature flag](https://caniuse.com/css-container-queries) in all Chromium-based browsers like Google Chrome, Microsoft Edge, Opera, and Vivaldi.

## Enable CSS Container Queries

Type `chrome://flags` in the address bar, and switch "Enable CSS Container Queries" to "enabled".

![Screenshot of setting the feature flags in Vivaldi browser](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/46f5b41nobvy8uqotn2h.png)

Restart your browser and you can start to experiment with container queries.

![Experimenting with container queries](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xzob4sr0twj91nbvcs7y.png)

I will follow-up on container queries experiments in this blog series.