DEV Community

Diana Le
Diana Le

Posted on

CSS Layouts: Maintain Element Proportions with aspect-ratio

Introduction

There are times you'll want to keep an object on a web page the same proportion on all devices and screens, and this is possible now with aspect-ratio. This property is useful for elements that do not have inherit proportions, such as <div> and <iframe>.

I've mostly used aspect-ratio for decorative or elements with minimal text. Be careful about using it for items with long passages of text, because you have to consider what happens when text overflows. And of course if you're trying to fit it within a layout to align with other components, then you're better off using properties like grid or flex.

Banner Example

Here's a simple banner example:


<!-- HTML -->
<div class="banner">
  <h1>Welcome to the Movies</h1>
  <div class="square-one"></div>
  <div class="square-two"></div>
</div>
Enter fullscreen mode Exit fullscreen mode

The banner uses aspect-ratio to keep it the same proportion (21:9) on every screen size. The aspect-ratio uses width / height as values (height default value is 1 if not declared). The banner has two decorative elements that also utilize aspect-ratio to keep the shapes and sizings consistent. These items don't necessarily have to keep the same proportions (they may change for artistic reasons depending on the viewport), but it's easy to do so now with aspect-ratio and not need to set explicit heights per viewport.

/* CSS */
.banner {
  position: relative;
  max-width: 1000px;
  width: 100%;
  margin: 1em auto;
  aspect-ratio: 21 / 9; /* Setting aspect-ratio */
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #00171f;
  overflow: hidden;
}

.square-one {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 30%;
  aspect-ratio: 5 / 4; /* Setting aspect-ratio */
  background-color: #007ea7;
}

.square-two {
  position: absolute;
  top: 0;
  right: 0;
  width: 80%;
  aspect-ratio: 7; /* Setting aspect-ratio */
  background-color: #003459;
}
Enter fullscreen mode Exit fullscreen mode

The two "squares" are decorative background shapes that keep both a consistent percentage width of the banner, and a consistent proportion. Resize the Codepen window and you can see that the banner and the decorative elements inside maintain the same proportions on all screens.

You can see how simple it is to just set the aspect-ratio value once and not have to worry about it. In the past I've had to use multiple media queries for banners with background images because there is no inherent size with them, and relying on changing the vertical padding or font sizes to keep the same ratio was tedious and never an exact match.

iframe Example

For an <iframe> such as an embedded YouTube video, making it responsive while keeping the original proportion is much easier than it used to be.

Clicking on the YouTube "share" button will give you a code snippet like so:

<!-- HTML -->
  <iframe 
    width="560" 
    height="315" 
    src=...>
  </iframe>
Enter fullscreen mode Exit fullscreen mode

We can use the width and height properties as the aspect-ratio and this will allow the video to be responsive keeping its original proportion:

/* CSS */
iframe {
  aspect-ratio: 560 / 315; /* width and height of video */
  max-width: 100%;
  height: auto;
}
Enter fullscreen mode Exit fullscreen mode

And that's it! Previously you had to position: absolute the <iframe> in a container, and set its padding-bottom: 56.25% which is the video height divided by the width (315 / 560). I used to just copy this block over and over without thinking exactly what it was doing just because I knew it would work:

/* Old CSS method */
.container {
  position: relative;
  padding-bottom: 56.25%;
}

iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
Enter fullscreen mode Exit fullscreen mode

This code will still work, and might still be needed if you're using a non-evergreen browser, but otherwise aspect-ratio is highly supported now.

If you only style the <iframe> without setting aspect-ratio, or without using the old container method, and you only set the width or max-width property on the <iframe>, you'll wind up with a more square-ish shape as the screen gets smaller because the height will not adjust automatically. The video will still play in the correct aspect-ratio, but you will get really thick letter-boxing on the top and bottom which will make it not look like a video while paused.

Images

For images, the proportion is inherently built in with the width and height attributes (which you should always specify), so you don't need aspect-ratio.

<img 
  src="./image.jpg" 
  alt="" 
  width="300" 
  height="200"> 
Enter fullscreen mode Exit fullscreen mode

The width and height are treated like an aspect-ratio that will keep the image the same proportion of 300 pixels wide by 200 pixels tall no matter how big or small the image gets. This also helps the browser determine how much space is needed before the image fully loads so you reduce any jarring content shifting AKA "cumulative layout shift" that affects site speed. So you probably won't need aspect-ratio for images, however it can be used in combination with width and height that you can read about here.

Top comments (0)