Equal Height Images with Flexbox

Images on the Web have a mind of their own. Want to place two fluid images side by side so that their heights are always equal? Flexbox to the rescue!

You can see the final demo here: equal height images with flexbox demo

This would be easy in the old days — set equal heights and appropriate width on each img element and you’re done! But being being responsive citizens we use responsive design and fluid images! So we have the following HTML markup for our images:

<div class="img-group">
	<div class="img-container1">
	<img src="image1.jpg" >
	</div>

	<div class="img-container2">
	<img src="image2.jpg" >
	</div>
</div>

The div with class img-group contains all the images we want to display at the same height. Each img is in its own container so that we can make it fluid using the CSS:

img{
	width:100%;
	height:auto;
}

This gives us the fluid images we want — the images scale with the size of their containers (see the first demo) and they are stacked vertically. Now we want to place these images horizontally next to each other and then, force them to have the same heights.

We can do this by either using a combination of float and width or a much cleaner way using Flexbox.

Float & Width

We can place the image containers side by side using float:left1 and setting the correct width on the image containers in CSS using percentage units. But what are the correct widths so that both images display at the same height?

We have to do some math to find the correct widths for each of the image container elements. Say the first image has an aspect ratio aspect1 =  0.5656 and the second image has an aspect ratio aspect2 = 1.7679. I have taken these numbers from the images used in the demo, you should pick your own! To get each image to display at the same height, we use the widths calculated as:

width1 = aspect1/(aspect1 + aspect2) = 24.238% width2 = aspect2/(aspect1 + aspect2) = 75.762%

So we use these widths as the width property of the image containers

.img-container1{
	width:24.238%;
}
.img-container2{
	width:75.762%;
}

We have our equal height fluid images! If we want some padding or border on the left/right side of either image container we can use box-sizing:border-box; on the image containers to maintain the equal heights of the images. But since margins sit outside the box, there is no way to put margins on the image containers while having the heights of the images be the same. Worse yet, if we add a third image with aspect ratio aspect3 = 1.0135 we have to go back and recalculate the widths of all the image containers!2

width1 = aspect1/(aspect1 + aspect2+ aspect3) = 16.899% width2 = aspect2/(aspect1 + aspect2+ aspect3) = 52.820% width3 = aspect3/(aspect1 + aspect2+ aspect3) = 30.281%

Clearly, this float and width method is hacky; there has to be a better way!

Enter Flexbox

Flexbox allows us to get our equal height fluid images very easily. Firstly, we want all images in the img-group to sit side by side. This is done by the CSS:

.img-group{
	display:flex;
}

Just that simple line makes the images sit side by side (see Flex on Image Group demo); no need for any float witchcraft.

display:flex on the image group makes the images sit side by side.

To make the images the same height we set the flex property 3 of each image container to match the aspect ratio of the image with the CSS

.img-container1{
	flex:0.5656;
}
.img-container2{
	flex:1.7679;
}

This tells each image container to fill up the space inside the image group according to the image’s aspect ratio. The browser does all the math needed to decide how to fit the images correctly. We have equal height flexible images (see Flex with aspect ratios demo).

setting the flex property of the image containers to match the aspect ratios of the images makes their heights equal.

We can easily add padding, border and margins to the left/right of either image container while keeping the equal heights(see the padding and margin demos).

padding and margins on the image containers without messing up the heights.

Now if we add our third image, we simply add a line of CSS for its container:

.img-container3{
	flex:1.0135;
}

Flexbox automatically calculates all the correct widths for the previous images (see More Images demo) and we don’t have to change the previous code!

add a third image without changing previous CSS.

Asides

If we have a responsive site (as we should) the images will get very small on small viewports and we might want them to stack vertically instead of sitting side by side. This can be done quite easily by putting the display:flex on the img-group inside a min-width media query. So on smaller screens we get vertically stacked images but on larger ones they sit next to each other with equal heights.

The flexbox method still requires us to know the image aspect ratios. Further, we have to insert a separate CSS flex rule for each image. I don’t know a good way around this. If anyone does let me know.