15

I am having some difficulty using Flexbox. The goal is to have a row that is the same height as the shortest child element. Take two images as examples, one has 200px height the other has 120px height. This example below works as intended when <img> elements are the direct children of the flex element.

.row {
  display: flex;
  width: 100%;
  background: orange;
}
<div class="row">
   <img src="https://s3.amazonaws.com/imagetest.com/purple_200.jpg" />
   <img src="https://s3.amazonaws.com/imagetest.com/teal_120.jpg" />
</div>

However, in the following example, the height of the flexbox element expands to the tallest child element:

.row {
  display: flex;
  width: 100%;
  background: orange;
}
<div class="row">
  <div class="col">
    <img src="https://s3.amazonaws.com/imagetest.com/purple_200.jpg" />
  </div>
  <div class="col">
    <img src="https://s3.amazonaws.com/imagetest.com/teal_120.jpg" />
  </div>
</div>

What is a solution to make <div class="row"> the height of the shortest child element?

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Joel Hoelting
  • 1,862
  • 2
  • 23
  • 45

3 Answers3

8

As pointed out by @Michael_B, the first example only appears correct because of align-items: stretch.

You cannot do this with flex, or pure CSS. If we had a CSS selector which could select the shortest sibling, then we could have done this - but we don't!

You can either use a fixed height for the parent:

.row {
  display: flex;
  width: 100%;
  height: 120px; /* fixed height */
  background-color: orange;
}
<div class="row">
   <img src="https://s3.amazonaws.com/imagetest.com/purple_200.jpg" />
   <img src="https://s3.amazonaws.com/imagetest.com/teal_120.jpg" />
</div>

Or use JavaScript to do the logic for you:

$( document ).ready(function() {
    var min_height = -1;  
    
    $("img").each(function(  ) {
        if ($(this).height() < min_height || min_height == -1) {
            min_height = $(this).height();
        }
        $('.row').height(min_height);
    })
    
    $("img").each(function(  ) {
        $(this).height(min_height);
    });
});
.row {
  display: flex;
  width: 100%;
  background-color: orange;
  align-items: flex-start
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
   <img src="https://s3.amazonaws.com/imagetest.com/purple_200.jpg" />
   <img src="https://s3.amazonaws.com/imagetest.com/teal_120.jpg" />
</div>
Hooman Bahreini
  • 14,480
  • 11
  • 70
  • 137
4

The goal is to have a row that is the same height as the shortest child element.

This is not something flexbox can do automatically.

You'll need to find a way to tell the container what the height is of the shortest child so it can adjust its height to match. JavaScript seems the way to go.


Take two images as examples, one has 200px height the other has 120px height. This example below works as intended when <img> elements are the direct children of the flex element.

"The example below works as intended..." I presume you mean the height of the row is the height of the shorter image (120px).

In fact, the row is 200px tall:

enter image description here

The shorter image is actually stretching from 120px to 200px because a default setting on a flex container is align-items: stretch, meaning that flex items will expand the full length of the cross-axis. (This is how flexbox can deliver a layout with equal height columns.)

If you override the default with, let's say, align-items: flex-start, you'll see clearly that the taller items sets the height of the container.

enter image description here

.row {
  display: flex;
  align-items: flex-start;  /* new */
  background: orange;
}
<div class="row">
  <img src="https://s3.amazonaws.com/imagetest.com/purple_200.jpg" />
  <img src="https://s3.amazonaws.com/imagetest.com/teal_120.jpg" />
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 1
    Thanks for the answer. Today I learned that align-items: stretch is a default flexbox rule. I had no idea about that one. You were right, I did think that the row was the height of the shorter image. Very informative, thank you! – Joel Hoelting Jan 23 '19 at 03:26
4

You can adjust the height of other columns to match the column of your choice (e.g. the shortest column) by positioning other columns absolutely in relation to the column wrapper.

Below you can find the solution with :not() to make it easier to indicate by a class name which column you want to pick as the column height reference
https://developer.mozilla.org/en-US/docs/Web/CSS/:not

No JavaScript needed!

.row {
  display: flex;
  background: orange;
}

img {
  vertical-align: top; /* to get rid of default bottom padding in images */
}

.row > div:not(.dynamic-max-height-column) {
  position: relative;
}

.row > div:not(.dynamic-max-height-column) > img {
  position: absolute;
  max-height: 100%;
}
<div class="row">
  <div class="dynamic-max-height-column">
    <img src="https://dummyimage.com/300x200/575757/ffffff" alt="">
  </div>
  <div>
    <img src="https://dummyimage.com/300x300/b3b3b3/ffffff" alt="" />
  </div>
</div>
Adrian Bienias
  • 829
  • 10
  • 16