Search code examples
javascripthtmlcssreactjsflexbox

How to make flex box with limit 2 elements per row?


I need to make a table which will contain up to 4 divs. But the divs in that table always should use maximum of avaliable space. And one one row should contain not more then 2 divs For instance if table contains 2 divs it should look like this enter image description here

If table has 3 divs then like this: enter image description here

And if contains 4 then it should look like that

enter image description here

To achieve it i wrote this code:

<div
  style={{
    height: '58vh', border: '1px solid #d9d9d9',
    borderRadius: '0px 0px 2px 2px',
    display: 'flex',
    flexDirection: 'row',
    flexWrap: 'wrap',
  }}
 >
   <div style={{background:'red', flex: 'auto', margin: '5px'}}
   <div style={{background:'green', flex: 'auto', margin: '5px'}}
   <div style={{background:'blue', flex: 'auto', margin: '5px'}}
   <div style={{background:'pink', flex: 'auto', margin: '5px'}}

 </div> 

But i missing something here. For 1 div and for 2 divs it works as planned. But for more.. This is my result for 3 divs enter image description here And for 4 divs enter image description here Can anyone advice me please what should i change in this code?

PS. Please don't judge my unevenly drawn squeres :)


Solution

  • Here is another case of a layout that is flexible but limited to 2 columns. In this case, the columns do not have the same width.

    Note that this is different from a grid as here you won't need media queries to have a responsive layout (with a grid you would need to switch to a single column at some break point). This layout will change when the columns are of equal length (50/50). The cells will jump and will be placed one under the other. In fact, this layout will work as if you were using container queries, which is even better :-).

    just before switch after the switch

    .container {
      display:flex;
      flex-wrap:wrap;
    }
    .inner:nth-child(2n+1) {
      flex:1 1 50%;
    }
    /* right column width
      this can however small or big or omitted */
    .inner:nth-child(2n) {
      min-width: 100px;
    }
    
    /* just colors and stuff*/
    .inner {
      padding:.5em;
      box-sizing: border-box;
    }
    .inner:nth-child(1) {
      background-color: lightpink;
    }
    .inner:nth-child(2) {
      background-color: lightgreen;
    }
    .inner:nth-child(3) {
      background-color: lightblue;
    }
    .inner:nth-child(4) {
      background-color: lightyellow;
    }
    <div class="container">
      <div class="inner">one</div>
      <div class="inner">two</div>
      <div class="inner">three</div>
      <div class="inner">four</div>
    </div>

    Note that I used flex shorthand property above.

    Why does it work you may ask? The first, red column needs 50% of the space and grows if it has more space. The next column (green block) needs 100px. So you already have 50% + 100px. Now comes the next block (blue block) which must be at least 50% wide. 50% + 100px + 50% is greater than 100%, so the blue block is moved to the next row. So the only requirement is that the blocks must be larger than 1px (50% + 1px + 50% is still larger then 100%). Clean and simple.