Search code examples
csscss-grid

CSS Grid min-content cell expanding based on neighbour


Ive got a CSS grid that's two columns, five rows (at a display above 768px). All the rows are set to "min-content" bar the last, being set to auto.
I've defined template grid areas, one for each "cell", with the exception of one that covers the 3rd to 5th row on the second column - named a6 (in the sample code)

enter image description here

When there is little or no content in a6, the grid behaves exactly as I desire. However, if when a bit more content is added to a6, the a5 and a7 areas expand in height, despite their content not changing.

CSS:

    html,
    body {
      height: 100vh;
      padding: 0;
      margin: 0;
    }

    .maingrid {
      height: 100%;
      padding-left: 15px;
      padding-right: 15px;
      background-color: red;
      display: grid;
      grid-template-rows: min-content min-content min-content min-content min-content min-content min-content auto;
      grid-template-areas: 'a1' 'a2' 'a3' 'a4' 'a5' 'a6' 'a7' 'a8';
      grid-row-gap: .2em;
    }

    @media only screen and (min-width:768px) {
      .maingrid {
        grid-template-columns: 9fr 3fr;
        grid-template-rows: min-content min-content min-content min-content auto;
        grid-template-areas: 'a1 a2' 'a3 a4' 'a5 a6' 'a7 a6' 'a8 a6';
        background-color: darkcyan;
      }
    }

    .maingrid div {
      background-color: black;
    }

    .a1 {
      grid-area: a1;
      background-color: pink !important;
    }

    .a2 {
      grid-area: a2;
      background-color: aliceblue !important;
    }

    .a3 {
      grid-area: a3;
      background-color: aqua !important;
    }

    .a5 {
      grid-area: a4;
      background-color: blue !important;
    }

    .a4 {
      grid-area: a5;
      background-color: brown !important;
    }

    .a6 {
      grid-area: a6;
      background-color: burlywood !important;
    }

    .a7 {
      grid-area: a7;
      background-color: chartreuse !important;
    }

    .a8 {
      grid-area: a8;
      background-color: darkorange !important;
    }

HTML:

<main class="maingrid">
  <div class="a1">BLAH</div>
  <div class="a2">BLAH</div>
  <div class="a3">BLAH</div>
  <div class="a4">BLAH</div>
  <div class="a5">BLAH</div>
  <div class="a6">
    at<br />at<br />
  </div>
  <div class="a7">BLAH</div>
  <div class="a8">
    <button type="button" onclick="BreakTheGrid();">click me :(</button>
  </div>
</main>

JS (just to get the toggle button to work):

var isBroken = false;

function BreakTheGrid() {
  if (!isBroken) {
    $('.a6').html("the<br/>left<br />columns<br />have<br />expanded<br />boo!<br />");
  } else {
    $('.a6').html("no<br/>issue");
  }
  isBroken = isBroken == false;
}

Here's a JSFiddle replicating the issue: https://jsfiddle.net/up6afdj4/
If you click the button in a8, you can toggle the content of a6, thus toggling the issue.

I've only just started messing around with CSS grid, so I expect its something I've got completely wrong, but I can't figure it :)


Solution

  • By applying auto to the fifth row, which includes the a6 grid area, you trigger the Grid auto stretch algorithm, which distributes free space among rows covered by the grid area (spec §11.5, §11.5.1 and §11.8).

    enter image description here

    If you switch from auto to 1fr, the last row then consumes all free space, pinning the rows above to the top.

    enter image description here

    revised demo

    For a more detailed explanation of auto space distribution, see my answers here:

    (Illustrations generated by Firefox DevTools Grid Inspector.)