Search code examples
cssgridcss-gridgrid-layout

CSS Grid layout with dynamic height


I need to create layout 2x2 blocks with min-width 500px and min-height 300px. (first img). I can collapse blue block (by click on it) to height 100px and the block which is below must fill the gap and become bigger. The same behaviour if lower block collapsed, the upper will stretch. (second img) if screen width > 1200, turn it into 4 columns with width:300px, height:600px (third img) enter image description here

I tried to do add for parent

            width: 100%;
            height: 100%;
            display: grid;
            grid-template-rows:  minmax(300px, 1fr) minmax(300px, 1fr);
            grid-template-columns: minmax(500px, 1fr) minmax(500px, 1fr);
            grid-column-gap: 25px;
            grid-row-gap: 25px;
}

and also added

  @media (min-width: 1200px) {
        .parent {
            grid-template-rows:  minmax(600px, 1fr);
            grid-template-columns:  repeat(4, minmax(300px, 1fr));
        }
    }

but I don't know how to implement collapsing


Solution

  • You can try like below. I added a checkbox to simulate the switch between (1) and (2)

    .container {
      display: grid;
      grid-template-columns: 1fr 1fr; /* 2 columns */
      grid-auto-flow: dense;
      
      gap: 20px;
      border:1px solid;
      height: 300px;
    }
    .container > div {
      display: flex;
      flex-direction: column;
      gap: 20px;
    }
    .container > div > div {
      flex-grow: 1; /* fill remaining height */
      height: 100%; /* we start with equal div */
      
      background: lightblue;
      font-size: 20px;
    }
    
    @media (max-width: 1200px) {
      /* update the height on toggle */
      input:checked ~ .container > div:first-child > div:last-child,
      input:checked ~ .container > div:last-child > div:first-child {
         height: 80px; 
      }
    }
    
    @media (min-width: 1200px) {
      .container {
        grid-template-columns: 1fr 1fr 1fr 1fr; /* 4 columns */
      }
      .container > div {
        display: contents; /* remove inner divs */
      }
      /* rectify the order */
      .container > div:first-child > div:last-child {
        grid-column: 3;
      }
    }
    <input type="checkbox">
    <div class="container">
      <div>
        <div> 1 </div>
        <div> 3 </div>
      </div>
      <div>
        <div> 2 </div>
        <div> 4 </div>
      </div>
    </div>