Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flex container with four divs, need three columns, second column with two rows

For a section on a page, I am trying to display two rectangular divs stacked up between two square divs on either side as big as the height of the two stacked divs, inside these divs are img tags.

I am using this markup because on mobile I want to be able to have them on an un-wrapped flex row with an overflow: hidden parent so I can use a swipe code to translate the X-axis. I am having problems creating this layout for desktop with this markup using the flexbox (No grid, need to support IE11). Has anyone done this layout with this markup? Thanks.

 <div class="flex_container">
   <div class='flex_child square'>
     <img...>
   </div>
   <div class='flex-child rect'>
     <img...>
   </div>
   <div class='flex-child rect'>
     <img...>
   </div>
   <div class='flex-child square'>
     <img...>
   </div>
 </div>

Example by image

like image 970
Álvaro Avatar asked Oct 26 '18 17:10

Álvaro


2 Answers

Assuming that this will be the main layout of your page you can try to set a fixed height and use column direction with flexbox:

.flex_container {
  height: 100vh; /*adjust this value like you want*/
  display: flex;
  flex-direction: column;
  flex-wrap:wrap;
}
.flex_child {
  background:purple;
  border:2px solid #fff;
  box-sizing:border-box;
  width:calc(100% / 3);
}
.square {
  flex:1 1 100%;
}
.rect {
  flex:1 1 47%;
}

body {
  margin: 0;
}
<div class="flex_container">
  <div class='flex_child square'></div>
  <div class='flex_child rect  '></div>
  <div class='flex_child rect  '></div>
  <div class='flex_child square'></div>
</div>

And in case you want a better browser support you can use float/inline-block by slightly adjust the classes making the 2 squares at the start:

.flex_container {
  height: 100vh; /*adjust this value like you want*/
}
.flex_child {
  background:purple;
  border:2px solid #fff;
  box-sizing:border-box;
  width:calc(100% / 3);
  height:100%;
}
.square:nth-child(1) {
  float:left;
}
.square:nth-child(2) {
  float:right;
}
.rect {
  display:inline-block;
  height:50%;
  vertical-align:top;
}

body {
  margin: 0;
}
<div class="flex_container">
  <div class='flex_child square'></div>
  <div class='flex_child square'></div>
  <div class='flex_child rect  '></div>
  <div class='flex_child rect  '></div>
</div>

In case you cannot also change the classes, use some negative margin to rectify the position of the last element:

.flex_container {
  height: 100vh; /*adjust this value like you want*/
}
.flex_child {
  background:purple;
  border:2px solid #fff;
  box-sizing:border-box;
  width:calc(100% / 3);
  height:100%;
}
.square:first-child {
  float:left;
}
.square:last-child {
  float:right;
  margin-top:-50vh;
}
.rect {
  display:inline-block;
  height:50%;
  vertical-align:top;
}

body {
  margin: 0;
}
<div class="flex_container">
  <div class='flex_child square'></div>
  <div class='flex_child rect  '></div>
  <div class='flex_child rect  '></div>
  <div class='flex_child square'></div>
</div>
like image 192
Temani Afif Avatar answered Sep 27 '22 22:09

Temani Afif


Making some major assumptions about your content, but you can use absolute positioning to align things. Essentially you can pull the middle two elements out of the document flow and mimic stacking through positioning.

In this case, when above 767px, the entire row is within the document flow. When below 767px, we re-position the inner two elements and set the container to justify-content: space-between to provide the visual space.

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.flex_container {
  position: relative;
  display: flex;
}

.flex_item {
  flex: 1;
  height: 120px;
  border: 1px solid orange;
  padding: 40px;
  background-color: red;
  text-align: center;
}

@media (max-width: 767px) {
  .flex_container {
    justify-content: space-between;
  }  

  .flex_item {
    padding: 20px;
  }
  
  .square {
    flex: 0 1 33%;
  }
  
  .rect {
    position: absolute;
    left: calc(100% / 3);
    width: calc(100% / 3);
    height: 50%;
  }
  .rect.three {
    top: 50%;
  }
}
<div class="flex_container">
  <div class="one flex_item square">
    One
  </div>
  <div class="two flex_item rect">
    Two
  </div>
  <div class="three flex_item rect">
    Three
  </div>
  <div class="four flex_item square">
    Four
  </div>
</div>

Again, be careful - this assumes you can control the height of the container and the dimensions of the content within. If not, this type of layout falls apart fairly easily. As stated in the other comments, if you want more structure and stability, it'd be better to wrap the inner elements with another flex element with flex-direction: column. Just know the risks!

like image 41
chazsolo Avatar answered Sep 27 '22 22:09

chazsolo