How to Maintain Image Aspect Ratios in Responsive Web Design

Consider a typical set of image gallery thumbnails:

<ul>
  <li><a href="#"><img src="http://lorempixel.com/320/180/abstract" /></a></li>
  <li><a href="#"><img src="http://lorempixel.com/320/180/city" /></a></li>
  <li><a href="#"><img src="http://lorempixel.com/352/198/technics" /></a></li>
</ul>

We can show this gallery at any size in a responsive page template using CSS (essential properties shown):

ul
{
  width: 100%;
  padding: 0;
  margin: 0 0 2em 0;
  list-style-type: none;
}

li
{
  float: left;
  width: 33.3%;
  padding: 0;
  margin: 0;
  background-color: #000;
  border: 10px solid #fff;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  overflow: hidden;
}

li a
{
  display: block;
  width: 100%;
}

img
{
  display: block;
  max-width: 100%;
}

This works well because all our images have the same 16:9 aspect ratio. The height of the image is exactly 56.25% of the width (9 divided by 16 expressed as a percentage).

responsive thumbnails

However, we web designers are paranoid: people conspire against us and supply photographs in an infinite range of sizes and aspect ratios, e.g.

<ul>
  <li><a href="#"><img src="http://lorempixel.com/320/180/abstract" /></a></li>
  <li><a href="#"><img src="http://lorempixel.com/320/320/city" /></a></li>
  <li><a href="#"><img src="http://lorempixel.com/200/150/technics" /></a></li>
</ul>

responsive thumbnails

There are various solutions to this problem:

  1. We could resize every image by hand. That’s time-consuming and tedious.
  2. We could implement a clever automated server-based image resizing solution. That could take a while and resulting images may not be as polished or optimized as we like.
  3. We could throw a diva-like tantrum and refuse to work under such conditions. Of course, that’s unprofessional and none of us would resort to such tactics (too often).

Or can we use CSS to solve the issue?

We can, but it’s not as straight-forward as you may expect. In the old fixed-width design days we would have known the width of our image placeholder. If it was 160px, we could make the height 90px and leave early for a beer. In this example, our width is 33.3% of the container minus 20px for the border on the left and right-hand edges. It could be any size so setting a fixed height will impede our required aspect ratio.

The Percentage Padding Ploy

A little-known quirk of padding is that setting a top or bottom percentage bases it on the width of the containing block. If your block is 100px in width, padding-top: 30%; will equate to 30 pixels. I suspect this was done to make rendering calculations easier since element heights are normally determined by their content. Besides, if you had a fixed-height parent of 300px and set padding-top: 200%; on a child, the parent would become at least 600px — thus leading to a recursive cascade which breaks the web.

Whatever the reason, it’s very useful since it permits you to set an intrinsic ratio, e.g.

#element
{
	position: relative;
	height: 0;
	padding: 56.25% 0 0 0;
}

This element will retain a 16:9 ratio based on the width of the container. The height has been set at 0px but, since we have set position: relative;, we can absolutely position any child element.

As far as I’m aware, the padding trick was first highlighted by Thierry Koblentz to create responsive videos, but the same concept can be applied to images or any other content. Let’s update our thumbnail CSS:

li a
{
  display: block;
  width: 100%;
  position: relative;
  height: 0;
  padding: 56.25% 0 0 0;
  overflow: hidden;
}

img
{
  position: absolute;
  display: block;
  max-width: 100%;
  max-height: 100%;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  margin: auto;
}

The result will show the image with black borders if it does not have a matching 16:9 dimension:

responsive thumbnails

View the demonstration code…

Play around with the CSS. Removing the image max-width or max-height can apply cropping effects rather than resizing. I hope you find it useful.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Anonymous

    I’d reached the same conclusion after using it for videos and I’ve been using it since for everything. Works like a charm.

  • James South

    I do something very similar here http://jimbobsquarepants.github.io/Responsive/css/media.html (Constrained Images) though I centre the image within the containing element.

  • Paul O’B

    Yes it’s a good technique and you can do similar using a percentage margin-top with the :after pseudo-element instead of padding but padding is easier. Both margin and padding refer to the width of the element.

    I also prefer to center the image (as James mentioned above) rather than have its width contained when images are tall and thus get very narrow.

    e.g.

    img {
    	display: block;
    	margin: auto;
    	-webkit-transition: all 2s ease-out;
    	transition: all 2s ease-out;
    }
    #aspect img {
    	position: absolute;
    	left: -999em;
    	right: -999em;
    	top: -999em;
    	bottom:-999em;
    }
    
    
  • rahulsahu013

    Nice article.

  • Anonymous

    OH YES.

  • john

    I’m still a beginner especially with CSS and this looks like a very useful tip to know. Thanks.

  • Anonymous

    Instead of float:left, 1. Flexbox, 2. grunt-autoprefixer, 3. old IE gets basic 1 column layout.

    *drops mic*

  • Linda

    I love this! Would not have figured this out myself, so Thanks!

  • Anonymous

    Great explanation of a handy technique! I’ve been struggling with situations like this and did resort to manually creating all the images. Thank you!

  • Anonymous

    It’s nice to have this in one place. I went through the ringer figuring out how to do this a few months back. Thanks for this very useful post.

  • Anonymous

    You can also use CSS object-fit and this polyfill I’ve recently published to maintain aspect-ratios / fit an image into wrapping elements. Might ease things a lot for some use-cases:
    https://github.com/anselmh/object-fit

  • Ahmad Ajmi

    Yes, this is what I was looking for instead of adjusting the height and with for many breakpoints I use. Thanks