Search code examples
csscss-grid

Is there a way to specify the entire first and last columns in auto-fit CSS grid?


I would like a css grid that looks like this:

┌─────────┬─────────┬─────────┬─────────┬─────────┐
│         │         │         │         │         │
│         │  item   │  item   │  item   │         │
│         │         │         │         │         │
│         ├─────────┼─────────┼─────────┤         │
│         │         │         │         │         │
│firstcol │  item   │  item   │  item   │ lastcol │
│         │         │         │         │         │
│         ├─────────┼─────────┼─────────┤         │
│         │         │         │         │         │
│         │  item   │  item   │  item   │         │
│         │         │         │         │         │
└─────────┴─────────┴─────────┴─────────┴─────────┘

that can resize responsively to:

┌─────────┬─────────┬─────────┬─────────┐
│         │         │         │         │
│         │  item   │  item   │         │
│         │         │         │         │
│         ├─────────┼─────────┤         │
│         │         │         │         │
│         │  item   │  item   │         │
│         │         │         │         │
│         ├─────────┼─────────┤         │
│         │         │         │         │
│firstcol │  item   │  item   │ lastcol │
│         │         │         │         │
│         ├─────────┼─────────┤         │
│         │         │         │         │
│         │  item   │  item   │         │
│         │         │         │         │
│         ├─────────┼─────────┤         │
│         │         │         │         │
│         │  item   │         │         │
│         │         │         │         │
└─────────┴─────────┘         └─────────┘

or narrower or wider, etc.

For the containing DIV, I've tried a repeats...

.container {
  display: grid;
  grid-template-columns: 100px repeat( auto-fit, minmax(250px, 1fr) ) 100px;
  grid-auto-flow: row; /* or column really ;-) - either is ok */
}

...and I've tried media queries:

.container {
  display: grid;
  grid-template-columns: 100px 1fr 100px;
  grid-auto-flow: column;
}

@media (min-width: 600px) {
  .container {
    grid-template-columns: 100px 1fr 1fr 100px;
  }
}

@media (min-width: 800px) {
  .container {
    grid-template-columns: 100px 1fr 1fr 1fr 100px;
  }
}

@media (min-width: 1200px) {
  .container {
    grid-template-columns: 100px 1fr 1fr 1fr 1fr 100px;
  }
}

For the containers, I've tried:

.firstcol {
  grid-column: 1 / span 1 ;
  grid-row: 1 / -1;
}

.lastcol {
  grid-column: -2 / -1 ;
  grid-row: 1 / -1;
}

... as well as variations on areas. I can't seem to get the first and last column areas specified dynamically.

Am I wrong? Is grid-row: 1 / -1; not meant to mean the 1st row to the last row, or ?


Solution

  • Here's what I went with, with apols to MMD's idea about flex box.

    The key was this:

    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));

    The minmax(150px, 1fr) fills in the row with elements of min size, but lets them stretch to fill the row.

    .entry {
      display: grid;
      grid-template-columns: 100px auto 100px;
    }
    
    .stats {
      display: grid;
      grid-gap: 5px;
      grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
      background-color: #fff;
      color: #444;
    }
    
    .item {
      display: grid;
      grid-template-columns: 1fr 1fr;
      padding: 0;
      margin: 0;
      font-size: 0.8em;
      margin: 5px;
      border: 1px solid gray;
    }
    
    .firstcol {
      margin: 5px;
      border: 1px solid lightsalmon;
    }
    
    .lastcol {
      margin: 0 padding: 0;
      margin: 5px;
      border: 1px solid lightblue;
    }
    <div class="entry">
      <div class="firstcol">Row #1</div>
      <div class="stats">
        <div class="item">A</div>
        <div class="item">B</div>
        <div class="item">C</div>
        <div class="item">D</div>
        <div class="item">E</div>
        <div class="item">F</div>
        <div class="item">G</div>
        <div class="item">H</div>
        <div class="item">I</div>
      </div>
      <div class="lastcol">
        <button>Action</button>
      </div>
    </div>
    <div class="entry">
      <div class="firstcol">Row #2</div>
      <div class="stats">
        <div class="item">A</div>
        <div class="item">B</div>
        <div class="item">C</div>
        <div class="item">D</div>
        <div class="item">E</div>
        <div class="item">F</div>
        <div class="item">G</div>
        <div class="item">H</div>
        <div class="item">I</div>
      </div>
      <div class="lastcol">
        <button>Action</button>
      </div>
    </div>
    <div class="entry">
      <div class="firstcol">Row #3</div>
      <div class="stats">
        <div class="item">A</div>
        <div class="item">B</div>
        <div class="item">C</div>
        <div class="item">D</div>
        <div class="item">E</div>
        <div class="item">F</div>
        <div class="item">G</div>
        <div class="item">H</div>
        <div class="item">I</div>
      </div>
      <div class="lastcol">
        <button>Action</button>
      </div>
    </div>