Agargara
Agargara

Reputation: 932

Shrink images to fit in flexbox with wrapping rows

I want an arbitrary number of images to shrink to fit inside a fixed-width div. It seems that flexbox is good for this purpose, but I can't seem to get it to work with wrapping multiple rows.

If I set flex-flow to row wrap and flex to 1 1 auto, the images are too big.

.container {
  display: flex;
  flex-flow: row wrap;
  border: 1px solid black;
  width: 300px;
  height: 300px;
}

.image {
  flex: 1 1 auto;
}

img {
  max-width: 100%;
}
<div class="container">
  <div class="image">
    <img src="http://www.placebacon.net/400/300">
  </div>
  <div class="image">
    <img src="http://www.placebacon.net/400/300">
  </div>
  <div class="image">
    <img src="http://www.placebacon.net/400/300">
  </div>
</div>

If I set flex-flow to just row or flex to 1 1 0, the images don't wrap onto multiple lines:

.container {
  display: flex;
  flex-flow: row wrap;
  border: 1px solid black;
  width: 300px;
  height: 300px;
}

.image {
  flex: 1 1 0;
}

img {
  max-width: 100%;
}
<div class="container">
  <div class="image">
    <img src="http://www.placebacon.net/400/300">
  </div>
  <div class="image">
    <img src="http://www.placebacon.net/400/300">
  </div>
  <div class="image">
    <img src="http://www.placebacon.net/400/300">
  </div>
</div>

How can I make the images expand enough to wrap as much as possible to fill the div, but not so much they break out of it?

Upvotes: 2

Views: 3550

Answers (2)

Michael Benjamin
Michael Benjamin

Reputation: 371143

If I set flex-flow to row wrap and flex to 1 1 auto, the images are too big.

With flex-basis: auto your item will take the size of its content (the image, in this case). That's what you're getting in your first demo: The intrinsic width of the image.

If I set flex-flow to just row or flex to 1 1 0, the images don't wrap onto multiple lines.

With flex-basis: 0 your item will ignore content size and distribute all space in the row evenly among items. That's what's happening in your second demo: It's creating three equal width items. As a result, there is no reason to wrap.

To control the size of flex items you need to define their flex-basis. Here's a rough sketch:

.container {
  display: flex;
  flex-flow: row wrap;
  align-content: flex-start; /* pack wrapping lines to the top */
  border: 1px solid black;
  width: 300px;
  height: 300px;
}

.image {
  flex: 0 0 30%;
  margin: 5px;
}

img {
  max-width: 100%;
}
<div class="container">
  <div class="image">
    <img src="http://www.placebacon.net/400/300">
  </div>
  <div class="image">
    <img src="http://www.placebacon.net/400/300">
  </div>
  <div class="image">
    <img src="http://www.placebacon.net/400/300">
  </div>
  <div class="image">
    <img src="http://www.placebacon.net/400/300">
  </div>
  <div class="image">
    <img src="http://www.placebacon.net/400/300">
  </div>  
</div>

Upvotes: 2

Ruslan
Ruslan

Reputation: 1303

Just for fun.

var container1 = document.querySelector('.container1'),
  container2 = document.querySelector('.container2'),
  img = container2.querySelectorAll('.container2 img'),
  width = 50,
  stop = false;

expand();

function expand() {
  for (var i = 0; i < img.length; i++) {
    img[i].style.width = width + 'px';
  }
  if (stop) return;
  if (container2.clientHeight < container1.clientHeight) {
    width++;
    setTimeout(function() {
      expand()
    }, 10);
  } else {
    width--;
    stop = true;
    expand();
  }
}
.container1 {
  border: 1px solid black;
  height: 300px;
  width: 300px;
}

.container2 {
  font-size: 0;
}
<div class="container1">
  <div class="container2">
    <img src="http://www.placebacon.net/400/300">
    <img src="http://www.placebacon.net/400/300">
    <img src="http://www.placebacon.net/400/300">
  </div>
</div>

Upvotes: 1

Related Questions