0

Is there any solution to avoid the float and to use flexbox and make this type of layout like in my representation? I don't have any example but this picture with what I need.

I'll try to explain in words:

  • This grid starts from 1025px and with 2 columns and the big red square in the right side.
  • From 1100px I need 3 columns and the big red square in the right
  • From 1680px I will have 4 columns and the big red square in the right.

 

  1. The position of the items must be like in my picture
  2. Depending of the aspect ratio, 4 items will go down with the others: 5,6,7,8 will go down with 9, 10, and so on.
  3. The big red must have always the same height with the first two rows.
  4. All the layout is fluid and responsive

I can make this very easy with FLOAT and some JS to calculate the exact same height of the first two rows and make the big red have the same but I want to use flexbox if its possible.

enter image description here

The code I have so far

.grid {
  display: flex;
  flex-direction: row;
}
.item {
  width: 16%;
  margin: 5px;
}
.red-box {
  
}
<div class="grid">
  <div class="red-box">big box</div>
  
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
  <div class="item">Item 4</div>
  <div class="item">Item 5</div>
  <div class="item">Item 6</div>
  <div class="item">Item 7</div>
  <div class="item">Item 8</div>
  <div class="item">Item 9</div>
  <div class="item">Item 10</div>  
  <div class="item">Item 11</div>
  <div class="item">Item 12</div>
  <div class="item">Item 13</div>
  <div class="item">Item 14</div>
  <div class="item">Item 15</div>
  <div class="item">Item 16</div>
  <div class="item">Item 17</div>
  <div class="item">Item 18</div>
  <div class="item">Item 19</div>
  <div class="item">Item 20</div>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • Possible duplicate https://stackoverflow.com/questions/46920900/how-can-i-use-flexbox-to-achieve-a-floating-sidebar-layout-with-content-that-wra – Asons Jan 25 '18 at 14:13
  • No, its not the same. Its more complicated here. I can't figure out –  Jan 25 '18 at 14:16
  • 1
    First off, as we don't write up code here, you need to provide the code snippet you come up with so far, second, this can't be done with Flexbox alone, so you need to make a compromise, which can be Flexbox/script, Flexbox/float, Flexbox/absolute, Float/script, ....or CSS Grid might be a solution. – Asons Jan 25 '18 at 14:19
  • 3
    *I can make this very easy with FLOAT* you said, then what's the point to make it complicated? – Stickers Jan 25 '18 at 14:20
  • I was wondering what If I can make this only with flex. No more javascript. –  Jan 25 '18 at 14:32
  • Perhaps you can ask another question for that of course you need to post your existing code. – Stickers Jan 25 '18 at 14:43
  • Look into CSS Grid https://css-tricks.com/snippets/css/complete-guide-grid/ – sol Jan 25 '18 at 14:58
  • @Stickers No point asking the same question twice. – Asons Jan 25 '18 at 15:06
  • @LGSon Bahaha ;) I mean asking the float without javascript. – Stickers Jan 25 '18 at 15:07
  • @Stickers Okay ... misunderstood you then :) – Asons Jan 25 '18 at 15:08
  • I have no code to show. I only have it created with float and some javascipt to calculate the height of the red box. That's all. –  Jan 25 '18 at 15:09
  • @StefanIordache That is exactly what is needed to be posted. – Asons Jan 25 '18 at 15:09
  • Ok, let me try to do some demo on jsfiddle. thanks –  Jan 25 '18 at 15:10
  • https://jsfiddle.net/nvybvl/3mmbvau1/1/ –  Jan 25 '18 at 15:18

2 Answers2

3

If you combine Flexbox with absolute position, you can accomplish that.

What I did was to make use of the order property to position the red element in the upper right corner. With this one can then control its position using media queries.

To force a wrap on the end of the 2nd row, I used a pseudo element with the same size as the right_corner element, and use the order property to position it.

To center the red element I use an absolute positioned wrapper and Flexbox, that will take twice its height, and by that cover 2 rows.

Stack snippet

.container {
  display: flex;
  flex-wrap: wrap;
  counter-reset: num;
}

.container .right_corner > div {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: calc(200% + 10px);
  display: flex;
  justify-content: center;
  align-items: center;
}

.container .right_corner > div > div {
  width: 300px;
  min-width: 300px;
  height: 250px;
  background: red;
}

.container::before,
.container > div {
  height: 150px;
  margin: 5px;
}

.container > div:not(:first-child) {
  background: lightgray;
}

.container .right_corner {
  position: relative;
  order: 1;
}

.container::before {
  content: '';
  order: 3;
}

.container > div:nth-child(n+2)::before {
  counter-increment: num;
  content: counter(num);
}

@media (max-width: 800px){
  .container > div:nth-child(n+4) {
    order: 2;
  }
  .container > div:nth-child(n+6) {
    order: 4;
  }
  .container > div:not(:first-child) {
    width: calc((100% / 4) - 10px);
  }
  .container .right_corner {
    width: calc((100% / 2) - 10px);
  }
  .container::before {
    width: calc((100% / 2) - 10px);
  } 
}

@media (min-width: 801px) and (max-width: 1000px){
  .container > div:nth-child(n+5) {
    order: 2;
  }
  .container > div:nth-child(n+8) {
    order: 4;
  }
  .container > div:not(:first-child) {
    width: calc((100% / 5) - 10px);
  }
  .container .right_corner {
    width: calc((100% / 2.5) - 10px);
  }
  .container::before {
    width: calc((100% / 2.5) - 10px);
  } 
}

@media (min-width: 1000px) {
  .container > div:nth-child(n+6) {
    order: 2;
  }
  .container > div:nth-child(n+10) {
    order: 4;
  }
  .container > div:not(:first-child) {
    width: calc((100% / 6) - 10px);
  }
  .container .right_corner {
    width: calc((100% / 3) - 10px);
  }
  .container::before {
    width: calc((100% / 3) - 10px);
  }
}
<div class='container'>

  <div class='right_corner'>
    <div>
      <div></div>
    </div>
  </div>

  <div></div>
  <div></div>
  <div></div>
  <div></div>
  
  <div></div>
  <div></div>
  <div></div>
  <div></div>

  <div></div>
  <div></div>
  <div></div>
  <div></div>

  <div></div>
  <div></div>
  <div></div>
  <div></div>

  <div></div>
  <div></div>
  <div></div>
  <div></div>

</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • Thanks for the answer. Looks very good but now I have to see how to keep the red block at the same height on every browser resize –  Jan 29 '18 at 08:44
  • @StefanIordache But it has the same height (in this sample I gave it 60%), even when you resize and the amount of column change. And if you need to change it, you can do that with the existing media query's. How do you mean it doesn't keep the same height? – Asons Jan 29 '18 at 08:50
  • the red block has to have 300x250 all the time (this has to have a fixed width and height) and to be vertically positioned in the middle. because the first 2 row will have more height than the red one. as you can see in my picture –  Jan 29 '18 at 09:24
  • @StefanIordache The solution I gave does that, but has now been updated with new values, where i.a. the _red block_ is 300x250. And with the media query you control at what break point the column amount should change, and with that avoid the _red block_ to overflap the other items. – Asons Jan 29 '18 at 09:35
  • Thank you. Seems to be perfectly what I need. –  Jan 29 '18 at 14:00
0

My attempt on jsfiddle.net. It is without absolute positioning and pseudo elements.

And the same code here in the below snippet:

body {
  background-color: black;  
}

.grid {
  display: flex;
  flex-flow: row wrap;
}

.grid > div {
  display: flex;
  justify-content: center;
  align-items: center;
}

.item {
  width: calc(33.33% - 10px);
  margin: 5px;
  height: 60px;
  background-color: gainsboro;  
}

.red-box {
  box-sizing: border-box;
  width: calc(33.33% - 60px);
  margin: 30px 30px;
  height: 80px;
  margin-bottom: -70px; 
  order: 2!important;
  background-color: red;
  border: 2px solid gainsboro;      
}

.red-box > div {
  background-color: red;
  height: 60%;
  width: 60%;
  border: 2px solid gainsboro; 
}    

@media (max-width: 499px) {
  .grid > div:nth-child(-n+3) {
    order: 1;
  }
  .grid > div:nth-child(n+4) {
    order: 3;
  }      
  .grid>div:nth-child(5) {
    margin-right: calc(33.33% + 5px);
  }
}

@media (min-width: 500px) and (max-width: 999px) {
  .grid > div:nth-child(-n+4) {
    order: 1;
  }
  .grid > div:nth-child(n+5) {
    order: 3;
  } 
  
  .item {
    width: calc(25% - 10px);
   }
   .red-box {
    width: calc(25% - 60px);
   }
   .grid>div:nth-child(7) {
     margin-right: calc(25% + 5px);
   }
}

@media (min-width: 1000px) {
  .grid > div:nth-child(-n+5) {
    order: 1;
  }
  .grid > div:nth-child(n+6) {
    order: 3;
  } 
  
  .item {
    width: calc(20% - 10px);
   }
   .red-box {
    width: calc(20% - 60px);
   }
   .grid>div:nth-child(9) {
     margin-right: calc(20% + 5px);
   }
}
<div class="grid">
  <div class="red-box"></div>

  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
  <div class="item">Item 4</div>
  <div class="item">Item 5</div>
  <div class="item">Item 6</div>
  <div class="item">Item 7</div>
  <div class="item">Item 8</div>
  <div class="item">Item 9</div>
  <div class="item">Item 10</div>  
  <div class="item">Item 11</div>
  <div class="item">Item 12</div>
  <div class="item">Item 13</div>
  <div class="item">Item 14</div>
  <div class="item">Item 15</div>
  <div class="item">Item 16</div>
  <div class="item">Item 17</div>
  <div class="item">Item 18</div>
  <div class="item">Item 19</div>
  <div class="item">Item 20</div>
</div>
Vadim Loboda
  • 2,431
  • 27
  • 44
  • Hi, the code looks very good but the only problem now its how to keep the red block at the same height on every resolution. –  Jan 29 '18 at 08:43