Search code examples
htmlcsscss-grid

CSS Grid Holy Grail not paying attention to HTML columns


Attempting a Holy Grail layout with a variable number of fixed and fluid width HTML columns that stretch to fill the space between the two ends.

The below CSS allows for a variable number of fixed and fluid width HTML columns that fill the space between the two ends...

*:before,
*:after,
*,
::after,
::before {
  box-sizing: border-box;
}

body {
  padding: 0;
  margin: 0;
  overflow: hidden;
}

app-container {
  grid-template-columns: 200px repeat(auto-fit, minmax(1rem, 1fr));
  display: grid;
  grid-gap: 1rem;
  background-color: beige;
  padding: 1rem;
  overflow: hidden;
}

app-panel {
  background: IndianRed;
  min-height: 5rem;
}

app-panel:last-of-type {
  grid-column: -1;
  width: 200px;
}
<app-container>
  <app-panel></app-panel>
  <app-panel></app-panel>
  <app-panel></app-panel>
  <app-panel></app-panel>
  <app-panel></app-panel>
</app-container>

... But when the first and last-of-type <app-panel> are grid-column: 1 / -1; (header and footer of the holy grail layout), the grid IGNORES the center HTML columns and instead adds as many grid columns as it can to fill the remaining space.

Why does it do that and how to get the center columns to keep stretching to fill the remaining space rather than the Grid filling in columns?

Thank you!

*:before,
*:after,
*,
::after,
::before {
  box-sizing: border-box;
}

body {
  padding: 0;
  margin: 0;
  overflow: hidden;
}

app-container {
  grid-template-columns: 200px repeat(auto-fit, minmax(1rem, 1fr));
  grid-template-rows: auto 1fr auto;
  display: grid;
  height: 100vh;
  grid-gap: 1rem;
  background-color: beige;
  padding: 1rem;
  overflow: hidden;
}

app-panel {
  background: IndianRed;
  min-height: 3rem;
}

app-panel:last-of-type,
app-panel:first-of-type {
  grid-column: 1 / -1;
}
<app-container>
  <app-panel></app-panel>
  <app-panel></app-panel>
  <app-panel></app-panel>
  <app-panel></app-panel>
  <app-panel></app-panel>
</app-container>

Modified code snippet originally from:

Combine "repeat" with "auto-fit" and fixed width column in a single "grid-template-columns"


Solution

  • A bit hacky but you can play with grid-row to place the element and adjust the width to simulate the full width behavior

    body {
      margin: 0;
    }
    
    app-container {
      grid-template-columns: 200px repeat(auto-fit, minmax(1rem, 1fr));
      grid-template-rows: auto 1fr auto;
      display: grid;
      height: 100vh;
      grid-gap: 1rem;
      background-color: beige;
      padding: 1rem;
      box-sizing: border-box;
      overflow: hidden;
    }
    
    app-panel {
      background: IndianRed;
      min-height: 3rem;
      grid-row: 2;
    }
    
    app-panel:nth-last-of-type(2) {
      grid-column: -1;
      width: 200px;
    }
    
    app-panel:first-of-type {
      grid-row: 1;
      width: calc(100vw - 2em);
    }
    app-panel:last-of-type {
      grid-row: 3;
      width: calc(100vw - 2em);
    }
    <app-container>
      <app-panel></app-panel>
      <app-panel></app-panel>
      <app-panel></app-panel>
      <app-panel></app-panel>
      <app-panel></app-panel>
      <app-panel></app-panel>
      <app-panel></app-panel>
    </app-container>