CSS Flexbox - Organizing flex items based on screen size

15,658

Since comments can be removed, and to keep their value, I decided to post an answer, with this code snippet as base.

div {
  box-sizing: border-box;
  width: 100%;
}

.container {
  display: flex;
  border: 1px solid red;
  flex-wrap: wrap;
  flex-direction: row;
  padding: 10px;
}

.cell {
  display: flex;
  flex: 50%;
  padding: 10px;
  border: 1px solid blue;
  height: 100px;
}

.data {
  width: 100%;
  justify-content: middle;
  flex: 1;
  border: 1px solid green;
}

@media only screen and (max-width: 1024px) {
  .container {
    display: inline-block;
    position: relative;
  }

  
  #cell1 { 
    width: 66%; 
    float: left;
  }
  
  #cell2 {
    flex-direction: column;
    right: 10px;
    position: absolute;
    width: 33%;
    height: 100%;
  }
  
  #cell3 { 
    width: 66%; 
    float: left;
  }
  
  #cell4 { display: none;}
}

@media only screen and (max-width: 640px) {
  
  #cell2 {
    flex-direction: row;
    position: static;
    height: 100px;
  }
  
  #cell4 { display: none; }
  
  .container { 
    flex-direction: row;
    flex-wrap: wrap;
    display: flex;
  }
  
  .cell { 
    flex: 100%; 
  }
}
<div class="container">
  <div class="cell" id="cell1">
    <span class="data">Image1</span>
    <span class="data">Info1</span>
  </div>
  <div class="cell" id="cell2">
    <span class="data">Image2</span>
    <span class="data">Info2</span>
  </div>
  <div class="cell" id="cell3">
    <span class="data">Image3</span>
    <span class="data">Info3</span>
  </div>
  <div class="cell" id="cell4">
    <span class="data">Image4</span>
    <span class="data">Info4</span>
  </div>
</div>

For it to work in tablet mode, you need to either make the container a flex column container, or use absolute or float to position the 2nd cell.

They all have limitations when it comes to responsiveness, where i.e. the flex column container solution will need a fixed height.

The one I find most usable is to stay with the default flex row set up, and combine it with absolute position on the 2nd cell.

This way the 1st and 3rd cell will continue being flex items, and benefit from its responsiveness.

In case of the 2nd cell's content making it higher than the 1st/3rd, one can then either allow it to scroll, or add a small script adjusting its parent's height.

Updated codepen

Stack snippet

div {
  box-sizing: border-box;
  width: 100%;
}

.container {
  display: flex;
  border: 1px solid red;
  flex-wrap: wrap;
  flex-direction: row;
  padding: 10px;
}

.cell {
  display: flex;
  flex: 50%;
  padding: 10px;
  border: 1px solid blue;
  height: 100px;
}

.data {
  width: 100%;
  justify-content: middle;
  flex: 1;
  border: 1px solid green;
}

@media only screen and (max-width: 640px) {
  
  #cell2 {
    flex-direction: row;
    position: static;
    height: 100px;
  }
  
  #cell4 { display: none; }
  
  .container { 
    flex-direction: row;
    flex-wrap: wrap;
    display: flex;
  }
  
  .cell { 
    flex: 100%; 
  }
}

@media only screen and (min-width: 640px) and (max-width: 1024px) {
  .container {
    position: relative;
  }
  
  #cell1 { 
    flex: 0 0 66%; 
  }
  
  #cell2 {
    flex-direction: column;
    right: 10px;
    position: absolute;
    width: 33%;
    height: calc(100% - 20px);
  }
  
  #cell3 { 
    flex:  0 0 66%; 
  }
  
  #cell4 { display: none;}
}
<div class="container">
  <div class="cell" id="cell1">
    <span class="data">Image1</span>
    <span class="data">Info1</span>
  </div>
  <div class="cell" id="cell2">
    <span class="data">Image2</span>
    <span class="data">Info2</span>
  </div>
  <div class="cell" id="cell3">
    <span class="data">Image3</span>
    <span class="data">Info3</span>
  </div>
  <div class="cell" id="cell4">
    <span class="data">Image4</span>
    <span class="data">Info4</span>
  </div>
</div>
Share:
15,658
jamesvphan
Author by

jamesvphan

Updated on June 09, 2022

Comments

  • jamesvphan
    jamesvphan almost 2 years

    I have a container of flex items that I am trying to organize in different layouts with different number of flex items depending on screen size. For example, on desktop, I'd like to have 4 containers, each with 2 items laid out in a 2x4 grid and each cell is 1x2. What I can't seem to wrap my head around is the getting the layout on tablet using purely with flexbox. Any pointers in the right direction would be great.

    div {
      box-sizing: border-box;
      width: 100%;
    }
    
    .container {
      display: flex;
      border: 1px solid red;
      flex-wrap: wrap;
      flex-direction: row;
      padding: 10px;
    }
    
    .cell {
      display: flex;
      flex: 50%;
      padding: 10px;
      border: 1px solid blue;
      height: 100px;
    }
    
    .data {
      width: 100%;
      justify-content: middle;
      flex: 1;
      border: 1px solid green;
    }
    
    @media only screen and (max-width: 1024px) {
      .container {
        display: inline-block;
        position: relative;
      }
    
      
      #cell1 { 
        width: 66%; 
        float: left;
      }
      
      #cell2 {
        flex-direction: column;
        right: 10px;
        position: absolute;
        width: 33%;
        height: 100%;
      }
      
      #cell3 { 
        width: 66%; 
        float: left;
      }
      
      #cell4 { display: none;}
    }
    
    @media only screen and (max-width: 640px) {
      
      #cell2 {
        flex-direction: row;
        position: static;
        height: 100px;
      }
      
      #cell4 { display: none; }
      
      .container { 
        flex-direction: row;
        flex-wrap: wrap;
        display: flex;
      }
      
      .cell { 
        flex: 100%; 
      }
    }
    <div class="container">
      <div class="cell" id="cell1">
        <span class="data">Image1</span>
        <span class="data">Info1</span>
      </div>
      <div class="cell" id="cell2">
        <span class="data">Image2</span>
        <span class="data">Info2</span>
      </div>
      <div class="cell" id="cell3">
        <span class="data">Image3</span>
        <span class="data">Info3</span>
      </div>
      <div class="cell" id="cell4">
        <span class="data">Image4</span>
        <span class="data">Info4</span>
      </div>
    </div>

    And here is a codepen here.

    Can test responsiveness by resizing window. I was able to correctly get the layouts that I want for desktop and mobile by removing the 4th container and changing flex-direction property. Struggling to do the same for tablet to allow spanning across multiple rows/columns in flex like you can in grid layouts.

    Desktop - container: 2x4 | cell: 1x2

    |---------------------------------|
    | --------------- --------------- |
    | | Cell | Cell | | Cell | Cell | |
    | --------------- --------------- |
    | --------------- --------------- |
    | | Cell | Cell | | Cell | Cell | |
    | --------------- --------------- | 
    |---------------------------------|
    

    Tablet - container: 2x3 | cell: 1x2/2x1

    |--------------------------|
    | --------------- -------- |
    | | Cell | Cell | | Cell | |
    | --------------- |______| |
    | --------------- |      | |
    | | Cell | Cell | | Cell | |
    | --------------- -------- |
    |--------------------------|
    

    Mobile - container: 3x2 | cell: 1x2

    |-----------------|
    | --------------- |
    | | Cell | Cell | |
    | --------------- |
    | --------------- |
    | | Cell | Cell | |
    | --------------- |
    | --------------- |
    | | Cell | Cell | | 
    | --------------- |
    |-----------------|