'CSS Flex item spanning two rows without fixed height

I am trying to create a flex container layout whereby one of the flex items should span two rows. See image below for a better explanation:

enter image description here

Here is my markup:

<div class="container">
    <div class="item item-1">ITEM 1</div>
    <div class="item item-2">ITEM 2</div>
    <div class="item item-3">ITEM 3</div>
</div>

I cannot seem to achieve this, I have tried using flex-wrap and different combinations of the flex property.

I was able to achieve this by putting ITEM 1 & ITEM 2 in a separate <div>, but this presents a problem on a smaller screen, whereby ITEM 3 needs to appear BETWEEN ITEM 1 & ITEM 2. So I would rather keep the markup as is and use the order property to move things around as necessary.



Solution 1:[1]

  1. You can't achieve it using flexbox. Instead, you should have two parents which are better.

  2. Use Css-grid. Actually, css-grid is the best option in this case.

Flex-Box

* {
  color: #fff;
}

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

.child {
  border-radius: 10px;
}

.container {
  display: flex;
  width: 500px;
  height: 200px;
  border: 1px solid #ff0000;
}

.container .first-item {
  flex-direction: column;
  justify-content: space-between;
  align-items: start;
  width: 50%;
  height: 100%;
  margin-right: 10px;
}

.first-item .child {
  width: 100%;
  height: 50%;
  background-color: blue;
}

.first-item .child:first-child {
  margin-bottom: 10px;
}

.container .second-item {
  width: 50%;
  height: 100%;
}

.second-item .child {
  width: 100%;
  height: 100%;
  background-color: blue;
}
<div class="container">
  <div class="first-item flex">
    <div class="child flex">Item 1</div>
    <div class="child flex">Item 2</div>
  </div>
  <div class="second-item flex">
    <div class="child flex">Item 3</div>
  </div>
</div>

Grid

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

.child {
  background-color: blue;
  border-radius: 10px;
}

.container {
  display: grid;
  grid-template-columns: 1fr 10px 1fr;
  grid-template-rows: 1fr 10px 1fr;
  grid-template-areas: "c1 . c3"
                       ".  . c3"
                       "c2 . c3";
 width: 500px;
  height: 300px;
  border: 1px solid red;
}

.container .child {
  border: 1px solid blue;
}

.child1 {
  grid-area: c1;
}

.child2 {
  grid-area: c2;
}

.child3 {
  grid-area: c3;
}
<div class="container">
  <div class="child child1 flex">Item 1</div>
  <div class="child child3 flex">Item 3</div>
  <div class="child child2 flex">Item 2</div>
</div>

Solution 2:[2]

i dont know if its a good solution but put two item3 codes one in the individual div (item1&2) and one outside then put the one in the div to display none in non-small screens and switch between them with mediaquery

@media (max-width: 40rem) {
.item3 {
display: none;
}
.mobile-item3{
display: block;
}
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Amini
Solution 2 Younes Chaouche