1

I am iterating over a list of items(red boxes). I have another element not part of this list that I want to insert into the items' grid in the top right(tall blue box). I am using flexbox and order to position it accordingly. But I want the 2nd row of red items to be 3 items wide and wrap inline with the blue aside. Screenshot of my ideal outcome below. Code at the bottom of my failed attempt.

enter image description here

.flex {
  display: flex;
  flex-wrap: wrap;
  margin: auto;
  max-width: 120px;
}

.flex>div {
  background: red;
  height: 25px;
  width: 25px;
  margin: 2px;
  order: 3;
}

.flex>div:nth-child(-n+3) {
  order: 1;
}

aside {
  height: 55px;
  width: 25px;
  margin: 2px;
  background: blue;
  order: 2;
}
<div class="flex">
  <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>
  <aside></aside>
</div>

Worth noting that I know I can do this with floats but for other reasons unrelated to this problem I'm kind of stuck with flexbox. Open to any & all suggestions though.

Asons
  • 84,923
  • 12
  • 110
  • 165
anthony-dandrea
  • 2,583
  • 7
  • 26
  • 46
  • CSS3 Grid layout would do wonders here – FelipeAls Jan 26 '18 at 09:54
  • May I ask why to accept an answer that is not dynamic. I mean, as soon as you change the value in e.g. `max-width: 120px`, it breaks, where in mine, it scales. – Asons Feb 02 '18 at 17:40

3 Answers3

2

Here is the problem you're facing with flexbox, and several potential solutions:

Here's a calculator keypad layout using flexbox:

Here's the cleanest and most efficient CSS solution, which uses Grid:

.flex {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 25px;
  grid-gap: 5px;
  margin: auto;
  max-width: 120px;
}

aside {
  grid-column: 4;
  grid-row: 1 / span 2;
  background: blue;
}

.flex > div {
  background: red;
}
<div class="flex">
  <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>
  <aside></aside>
</div>

jsfiddle demo

css grid browser support

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
1

Here is a version of another answer of mine, which might also qualify as a duplicate, though since it has a simpler CSS, I decided to post it as an answer.

It uses the order property and absolute position, to enable the required layout.

Read more here: Flexbox or Column CSS for positioning elements like this

Stack snippet

.container {
  display: flex;
  flex-wrap: wrap;
}

.container .right_corner > div {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: calc(200% + 10px);
  background: blue;
}

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

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

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

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

@media (max-width: 600px){
  .container > div:nth-child(n+5) {
    order: 2;
  }
  .container > div:nth-child(n+8) {
    order: 4;
  }
  .container::before,
  .container > div {
    width: calc((100% / 4) - 10px);
  }
}

@media (min-width: 601px) and (max-width: 800px){
  .container > div:nth-child(n+6) {
    order: 2;
  }
  .container > div:nth-child(n+10) {
    order: 4;
  }
  .container::before,
  .container > div {
    width: calc((100% / 5) - 10px);
  }
}

@media (min-width: 800px) {
  .container > div:nth-child(n+7) {
    order: 2;
  }
  .container > div:nth-child(n+12) {
    order: 4;
  }
  .container::before,
  .container > div {
    width: calc((100% / 6) - 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>
Asons
  • 84,923
  • 12
  • 110
  • 165
1

.flex {
  display: flex;
  flex-wrap: wrap;
  margin: auto;
  max-width: 120px;
}

.flex>div {
  background: red;
  height: 25px;
  width: 25px;
  margin: 2px;
  order: 3;
}

.flex>div:nth-child(-n+3) {
  order: 1;
}

aside {
  height: 55px;
  width: 25px;
  margin: 2px;
  background: blue;
  order: 2;
  margin-bottom: -57px;  /* added */
}

.flex>div:nth-child(6) { /* added */
  margin-right: 27px;
}
<div class="flex">
  <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>
  <aside></aside>
</div>
Vadim Loboda
  • 2,431
  • 27
  • 44
  • This is the solution that best fit my use case. The ideal way is to use css grid. But as that isn't as well supported as flexbox currently I opted for this fully flexbox solution. – anthony-dandrea Feb 01 '18 at 00:48