3

I am trying to create a flexbox grid with images that have different widths and heights which i want to behave responsive when shown on different screen sizes. I have the grid now, but i do not know how to make it responsive. I have tried to apply responsive classes within bootstrap to the current layout but without any luck. I have also tried masonry, but it did not solve my problem.

So the question is, how do i make this responsive and is it even the right approach?

enter image description here

HTML

<div class="flex_container">
  <div class="flex_group__1">
    <img src="holder.js/460x670" />
    <img src="holder.js/460x408" />
  </div>
  <div class="flex_group__2">
    <img src="holder.js/645x813">
    <img src="holder.js/645x265">
  </div>
  <div class="flex_group__3">
    <img src="holder.js/808x330"/>
    <div class="flex_group__3_inner_bottom">
      <img src="holder.js/452x748"/>
      <img src="holder.js/356x748"/>
    </div>
  </div>
</div>

CSS

.flex_group__1, .flex_group__2, .flex_group__3, .flex_group__3_inner_bottom, .flex_container {
  display: flex;
}

.flex_container {
  flex-direction: row;
}

.flex_group__3 {
  flex-direction: row wrap;
  justify-content: flex-end;
}

.flex_group__1, .flex_group__2, .flex_group__3 {
  flex-direction: column;
}

.flex_container * {
  border: 1px solid;
}
img {
  max-width: 100%;
}
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
JavaCake
  • 4,075
  • 14
  • 62
  • 125

1 Answers1

1

Here is a version with a layout closer to the one you asked for, and easier to follow.

With this you either set background-image (as I did in below stack snippet) on each image holder, or add an img element to the markup.

Fiddle demo

html, body {
  margin: 0;
}
.wrapper {
  position: relative;
}
.wrapper:after {
  padding-top: 56.25%;   /* 16:9 ratio */
  display: block;
  content: ' ';
}
.flex-container {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  padding: 5px;
  display: flex;
}
.flex-container > div {           /*  .flex-col-1, .flex-col-2, .flex-col-3  */
  height: 100%;
  display: flex;
  flex-direction: column;
}
.flex-container > div > div {     /*  .flex-row-1, .flex-row-2    */
  margin: 5px;
  display: flex;
}

.flex-col-1 {
  width: 25%;
}
  .flex-col-1 .flex-row-1 {
    height: 70%;
    background: #ddd url(https://placeimg.com/400/600/arch) no-repeat center;
    background-size: cover;
  }
  .flex-col-1 .flex-row-2 {
    height: 30%;
    background: #ddd url(https://placeimg.com/400/600/arch) no-repeat center;
    background-size: cover;
  }

.flex-col-2 {
  width: 32.5%;
}
  .flex-col-2 .flex-row-1 {
    height: 80%;
    background: #ddd url(https://placeimg.com/400/600/arch) no-repeat center;
    background-size: cover;
  }
  .flex-col-2 .flex-row-2 {
    height: 20%;
    background: #ddd url(https://placeimg.com/400/600/arch) no-repeat center;
    background-size: cover;
  }

.flex-col-3 {
  width: 42.5%;
}
  .flex-col-3 .flex-row-1 {
    height: 44%;
    background: #ddd url(https://placeimg.com/400/600/arch) no-repeat center;
    background-size: cover;
  }
  .flex-col-3 .flex-row-2 {
    height: 56%;
  }

.flex-col-3-inner {
  flex: 1;
  display: flex;
}
  .flex-col-3-inner .flex-col-1-inner {
    width: 40%;
    margin-right: 5px;
    background: #ddd url(https://placeimg.com/400/600/arch) no-repeat center;
    background-size: cover;
  }
  .flex-col-3-inner .flex-col-2-inner {
    width: 60%;
    margin-left: 5px;
    background: #ddd url(https://placeimg.com/400/600/arch) no-repeat center;
    background-size: cover;
  }
<div class="wrapper">
  <div class="flex-container">
    <div class="flex-col-1">
      <div class="flex-row-1">
      </div>
      <div class="flex-row-2">
      </div>
    </div>
    <div class="flex-col-2">
      <div class="flex-row-1">
      </div>
      <div class="flex-row-2">
      </div>
    </div>
    <div class="flex-col-3">
      <div class="flex-row-1">
      </div>
      <div class="flex-row-2">
        <div class="flex-col-3-inner">
          <div class="flex-col-1-inner">
          </div>
          <div class="flex-col-2-inner">
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

2:nd sample, using img, where I also added this rule

.flex-container img {
  height: auto;
  width: 100%;
}

and as you can see, with a layout like this, img elements need more individual touch to make them behave.

html, body {
  margin: 0;
}
.wrapper {
  position: relative;
}
.wrapper:after {
  padding-top: 56.25%;   /* 16:9 ratio */
  display: block;
  content: ' ';
}
.flex-container {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  padding: 5px;
  display: flex;
}
.flex-container > div {           /*  .flex-col-1, .flex-col-2, .flex-col-3  */
  height: 100%;
  display: flex;
  flex-direction: column;
}
.flex-container > div > div {     /*  .flex-row-1, .flex-row-2    */
  margin: 5px;
  display: flex;
}

.flex-container img {
  height: auto;
  width: 100%;
}

.flex-col-1 {
  width: 25%;
}
  .flex-col-1 .flex-row-1 {
    height: 70%;
    background: #ddd;
  }
  .flex-col-1 .flex-row-2 {
    height: 30%;
    background: #ddd;
  }

.flex-col-2 {
  width: 32.5%;
}
  .flex-col-2 .flex-row-1 {
    height: 80%;
    background: #ddd;
  }
  .flex-col-2 .flex-row-2 {
    height: 20%;
    background: #ddd;
  }

.flex-col-3 {
  width: 42.5%;
}
  .flex-col-3 .flex-row-1 {
    height: 44%;
    background: #ddd;
  }
  .flex-col-3 .flex-row-2 {
    height: 56%;
  }

.flex-col-3-inner {
  flex: 1;
  display: flex;
}
  .flex-col-3-inner .flex-col-1-inner {
    width: 40%;
    margin-right: 5px;
    background: #ddd;
  }
  .flex-col-3-inner .flex-col-2-inner {
    width: 60%;
    margin-left: 5px;
    background: #ddd;
  }
<div class="wrapper">
  <div class="flex-container">
    <div class="flex-col-1">
      <div class="flex-row-1">
        <img src="https://placeimg.com/400/600/arch" alt="">
      </div>
      <div class="flex-row-2">
        <img src="https://placeimg.com/400/600/arch" alt="">
      </div>
    </div>
    <div class="flex-col-2">
      <div class="flex-row-1">
        <img src="https://placeimg.com/400/600/arch" alt="">
      </div>
      <div class="flex-row-2">
        <img src="https://placeimg.com/400/600/arch" alt="">
      </div>
    </div>
    <div class="flex-col-3">
      <div class="flex-row-1">
        <img src="https://placeimg.com/400/600/arch" alt="">
      </div>
      <div class="flex-row-2">
        <div class="flex-col-3-inner">
          <div class="flex-col-1-inner">
            <img src="https://placeimg.com/400/600/arch" alt="">
          </div>
          <div class="flex-col-2-inner">
            <img src="https://placeimg.com/400/600/arch" alt="">
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Here are 2 more variants, one using background-size: contain;

and the other background-size: 100% 100%

Asons
  • 84,923
  • 12
  • 110
  • 165
  • Very awesome example! It made me realise that i should design it much more simpler next time ;-) Apart from that, when i add the images as to the flex boxes, some of them are stretched, which they shouldn't be. Is that the behavior as expected? – JavaCake Mar 24 '16 at 14:35
  • @JavaCake Thanks, and it is, unless you set them up one-by-one. I updated and added a 2:nd sample + an extra CSS rule, play with that and you'll see what happens. Probably you'll need to set individual values on each image, so using `background-image` has some benefits though, especially as you have such predefined layout. – Asons Mar 24 '16 at 14:54
  • I see what you mean, because i stumbled into the same problem as there is with this example. The two images on the lower corner are a bit "out of control".. – JavaCake Mar 24 '16 at 16:02
  • @JavaCake Yepp, and as each image needs to fit within a certain aspect ratio, you have to set that up, or else they will distort. The `background-size: cover` does that automatically and cut the image either at height or width, so when using `img` one need to set that up for each image. – Asons Mar 24 '16 at 16:07
  • So i need to calculate the pixels to percent for each flex cell in order for this to function properly? – JavaCake Mar 24 '16 at 16:09
  • @JavaCake I will see how I can make a sample to show what I mean, meanwhile, may I ask why you want `img` in favor of `background-image`? – Asons Mar 24 '16 at 16:14
  • Because i would like to see the entire image rather than a part of it, which is basically the downside for using roughly estimated widths. – JavaCake Mar 24 '16 at 16:15
  • @JavaCake Okay, what should happen when the image's height/width doesn't fit inside the flex holder, like being to wide or to high? ... Should the background shine through? – Asons Mar 24 '16 at 16:17
  • @JavaCake Check this demo, all images fully visible, though when they don't have same aspect ratio, background color will cover the rest of the flex holders area: https://jsfiddle.net/LGSon/htjccmfg/1/ – Asons Mar 24 '16 at 16:22
  • @JavaCake And this version squeeze them to fit: https://jsfiddle.net/LGSon/htjccmfg/2/ – Asons Mar 24 '16 at 16:29
  • I am considering a very cumbersome solution based on your example where i benefit from calc and possibly JS calculating the width and height in percentage. I have just made a simple example which works. – JavaCake Mar 24 '16 at 16:29
  • Those are two very interesting examples, but i cannot avoid setting some crazy width and height sizes which reflect the real values of the images for now, but i am considering JS to set the values accordingly just to avoid sitting with a calculator and finding the real percent value of the image. I have to say that the basis is really good. – JavaCake Mar 24 '16 at 16:37
  • @JavaCake No matter which solution, either the flex holder need to adjust or the image, and the image can either be cut or distort or leave unused space at side or top/bottom. – Asons Mar 24 '16 at 16:37
  • I can use this example, and simply adjust the width and height of the boxes. That would get me to the goal quite fast, and perhaps rather static, but it does not really matter at this stage. – JavaCake Mar 24 '16 at 16:38
  • @JavaCake I just hope what I tried to make use see is, that it is quite easy to do when you wrap your head around it a little. – Asons Mar 24 '16 at 16:41
  • I was hoping for a much smarter solution, but this would of course be an attempt to search for the golden unicorn. Initially i thought that the isotope/masonry library would be able to do all these "silly" calculations for me as a part of the framework, but it does not really do as i want it to. As long as i do not change the structure and measure the elements sizes by using JS i should have a somewhat flexible grid. – JavaCake Mar 24 '16 at 16:43