Search code examples
htmlcssflexboxgridresponsive

Responsive grid that responsively resizes to fit parent div, preserving parent div's own responsive height


I need a grid of squares that responsively (page resize) fills, but does not expand, its parent div.

The basic structure I have is below, with the parent div at 50% height of page. I want the grid to "resize" itself automatically to fit into this 50%. At the moment, the grid overflows. JSFiddle follows.

    .view {
        display: grid;
        grid-template-rows: 10% 50% 40%
    }

    .gridContainer {
        display: grid;
        grid-template-columns: repeat(5, 1fr);
    }

    .gridCell {
        aspect-ratio: 1 / 1;
        border: 1px solid #000
    }



    <div class="view">
        <div>TOP 10%</div>
        <div class="gridContainer"> <!-- 50% height -->
            <!-- 1st row --->
            <div class="gridCell">col1 row1</div>
            <div class="gridCell">col2 row1</div>
            <div class="gridCell">col3 row1</div>
            <div class="gridCell">col4 row1</div>
            <div class="gridCell">col5 row1</div>
            <!-- 2nd row --->
            <div class="gridCell">col1 row2</div>
            <div class="gridCell">col2 row2</div>
            <div class="gridCell">col3 row2</div>
            <div class="gridCell">col4 row2</div>
            <div class="gridCell">col5 row2</div>
            <!-- etc. to 5th row -->
        </div>
        <div>BOTTOM 40%</div>
    </div>

The problem is that the gridCells overflow at the bottom and get cropped/go out of bounds. Here's the JSFiddle demonstrating the problem...

https://jsfiddle.net/r5ezfaxu/4/

What I'm hoping to have happen is for the entire 5x5 grid to appear centered in the green area, at it maximum fitting size. I recognize that this will cause pillar boxing (which is vertical gaps, vs letter boxing which is horizontal gaps).

I've tried the code above with a variety of flex box and grid tweaks, but I'm at a loss. Please advise!


Solution

  • Try this. It uses containment units to get the cells the right size:

    .view {
      display: grid;
      grid-template-rows: 10% 50% 40%;
      height: calc(100vh - 16px);  /* viewport height - body margins */
    }
    
    .gridContainer {
      container-type: size;
      display:flex;
    }
    
    .grid {
      display: grid;
      height: 100cqmin;  /* min of the height and width of the grid container */
      container-type: size;
      aspect-ratio: 1 / 1;  /* width matches height */
      margin: auto;  /* centres the grid in the grid container */
      grid-template-columns: repeat(5, auto);
    }
    
    .gridCell {
      height: 20cqb;  /* One fifth of the grid size */
      aspect-ratio: 1 / 1;  /* cells are square */
      box-sizing: border-box;
      border: 1px solid #000
    }
        <div class="view">
          <div style="background-color: #f00">TOP 10%</div>
          <div class="gridContainer"  style="background-color: #0f0">
            <div class="grid">
              <!-- 1st row --->
              <div class="gridCell">1</div>
              <div class="gridCell">2</div>
              <div class="gridCell">3</div>
              <div class="gridCell">4</div>
              <div class="gridCell">5</div>
              <!-- 2nd row --->
              <div class="gridCell">1</div>
              <div class="gridCell">2</div>
              <div class="gridCell">3</div>
              <div class="gridCell">4</div>
              <div class="gridCell">5</div>
              <!-- etc. to 5th row -->
              <div class="gridCell">1</div>
              <div class="gridCell">2</div>
              <div class="gridCell">3</div>
              <div class="gridCell">4</div>
              <div class="gridCell">5</div>
    
              <div class="gridCell">1</div>
              <div class="gridCell">2</div>
              <div class="gridCell">3</div>
              <div class="gridCell">4</div>
              <div class="gridCell">5</div>
    
              <div class="gridCell">1</div>
              <div class="gridCell">2</div>
              <div class="gridCell">3</div>
              <div class="gridCell">4</div>
              <div class="gridCell">5</div>
            </div>
          </div>
          <div style="background-color: #00f">BOTTOM 40%</div>
        </div>