5

Is there a way to have flex items within a flex container with flex-direction: column have the same height, using CSS only?

<div style="display: flex; flex-direction: column;">
 <div class="flex-item">
   <!-- other html elements with image, links, button etc. -->
 </div>
 <!-- ... -->
 <div class="flex-item"></div>
</div>

JSFiddle: https://jsfiddle.net/hzxa9v54/

TylerH
  • 20,799
  • 66
  • 75
  • 101
mcmxc
  • 574
  • 1
  • 7
  • 19

2 Answers2

3

You will need a script to solve that using Flexbox, here done using jQuery.

Updated fiddle

Stack snippet

(function ($) {

  // preload object array to gain performance
  var $items = $('.item')
  
  // run at resize
  $( window ).resize(function() {
    $.fn.setHeight(0);   
  });  

  $.fn.setHeight = function(height) {

    // reset to auto or else we can't check height
    $($items).css({ 'height': 'auto' });
    
    // get highest value
    $($items).each(function(i, obj) {    
      height = Math.max(height, $(obj).outerHeight()) 
    });

    // set the height
    $($items).css({ 'height': height + 'px' });    
  }

  // run at load
  $.fn.setHeight(0);
  
}(jQuery));
.container {
  display: flex;
  flex-direction: column;
  width: 200px;
}
.item {
  border: 1px solid #ddd;
  margin: 10px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="item">
    come content 1
  </div>
  <div class="item">
    come content 2
    come content 3
  </div>
  <div class="item">
    come content 4
    come content 5
    come content 6
  </div>
  <div class="item">
    come content 7
  </div>
</div>

Update based on a comment, where e.g. also loading images needs to be taken into account.

Here is an updated version of the script, that adjust after image loads.

(function ($) {

  // preload object array to gain performance
  var $items = $('.item')
  
  // run at resize
  $( window ).resize(function() {
    $.fn.setHeight(0);   
  });  

  $.fn.setHeight = function(height) {

    // reset to auto or else we can't check height
    $($items).css({ 'height': 'auto' });
    
    // get highest value
    $($items).each(function(i, obj) {    
      height = Math.max(height, $(obj).outerHeight()) 
    });

    // set the height
    $($items).css({ 'height': height + 'px' });    
  }

  function imageLoaded() {
    $.fn.setHeight(0);
  }
  
  var images = $('.item img');
  if (images) {
    images.each(function() {
      if( this.complete ) {
        imageLoaded.call( this );
      } else {
        $(this).one('load', imageLoaded);
      }
    });
  } else {
    // run at load
    $.fn.setHeight(0);
  }

}(jQuery));
.container {
  display: flex;
  flex-direction: column;
  width: 200px;
}
.item {
  border: 1px solid #ddd;
  margin: 10px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="item">
    come content 1
  </div>
  <div class="item">    
    <img src="http://placehold.it/200x100/f00" alt="">
  </div>
  <div class="item">
    come content 4
    come content 5
    come content 6
  </div>
  <div class="item">
    come content 7
  </div>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • one problem - if there is an image inside, I need to wait until all of them fully loaded.. is there any way to do that, without including any libraries? – mcmxc Jan 17 '18 at 16:35
  • @mcmxc Let me know if the suggested solution for images work, and I will add it to my answer. – Asons Jan 18 '18 at 10:06
  • thanks mate, works great. Script does all the work, not even necessary to use flex box layout. Thanks a lot! – mcmxc Jan 18 '18 at 10:33
1

UPDATED: using your fiddle, i made slight modifications and used flex: 1 1 100%; on the flex children and it appears to be working.

updated fiddle: https://jsfiddle.net/hzxa9v54/4/

philr
  • 1,860
  • 1
  • 21
  • 31
  • That's not entirely true : you need to also give them the same flex-basis, and same flex-shrink. Or is it a shortcut for `flex: 1 1 auto;` ? –  Jan 17 '18 at 15:56
  • 1
    @trichetriche it is actually a shortcut for `flex: 1 1 0;` which is pretty much equivalent to `flex: 1 1 auto;` meaning there is no minimum height (in this case) for the div – philr Jan 17 '18 at 15:57
  • @trichetriche no problem – philr Jan 17 '18 at 16:01
  • @trichetriche and philr, `flex: 1 1 0` is far from equivalent to `flex: 1 1 auto`, where in the latter, the content is taken into account before the flex growth is calculated – Asons Jan 17 '18 at 16:01
  • Sure @LGSon, but I was asking if this was a shortcut, and he said precisely that it is a shortcut for `1 1 0`, so it answered my question. –  Jan 17 '18 at 16:04
  • @LGSon you're right, my bad `flex-basis: 0;` and `flex-basis: auto;` are not the same – philr Jan 17 '18 at 16:06
  • 1
    Furthermore, as the parent doesn't have a set height to fill, and as the content might differ in size, this can't be done w/o script. – Asons Jan 17 '18 at 16:09
  • @philr the problem is that the content is different and I need to make each flex-item to have a height as largest item has. fiddle https://jsfiddle.net/hzxa9v54/ – mcmxc Jan 17 '18 at 16:13
  • @mcmxc in that case, LGSon is correct. You need a script – philr Jan 17 '18 at 16:16