CSS Grid with variable number of “auto” rows, but one row should take “1fr”

Considering your three requirements:

  1. A grid with a variable number of rows.
  2. Every row should have a variable size (auto will do).
  3. The last row should always take up all the remaining space.

Flexbox is well-suited for the job. In fact, it may be the perfect fit (depending on your other requirements). I’ve provided a code sample below.

But if Grid Layout is what you want, then I think you’re going to be disappointed. I don’t believe Level 1 can do the job.

The closest you can get would be:

grid-template-rows: repeat(auto-fit, minmax(auto, 1px)) 1fr;

But it won’t work because the current grid spec doesn’t support this syntax.

repeat(auto-fit, auto) 1fr

This is the code you tried. It’s not valid because auto and fr cannot be used with auto-fit.

7.2.2.1. Syntax of
repeat()

Automatic repetitions (auto-fill or auto-fit) cannot be combined
with intrinsic or flexible sizes.

  • An intrinsic sizing function is min-content, max-content, auto, fit-content().

  • A flexible sizing function is <flex> (fr).

You can get around the auto limitation with something like this:

repeat(auto-fit, minmax(auto, 1px)) 1fr

minmax(min,max)

Defines a size range greater than or equal to min and less than or
equal to max.

If max < min, then max is ignored and minmax(min,max) is treated as min.

As a maximum, a <flex> value sets the track’s flex factor; it is invalid as a minimum.

That works to properly auto-size your rows, whether the container has the default auto height or a height / min-height defined. demo

But it still doesn’t solve the last row problem, since the 1fr remains invalid, and causes the entire rule to fail. demo

Something like this would be valid:

repeat(auto-fit, minmax(auto, 1px)) 10em

But the auto-fit doesn’t work as you expect: the 10em is applied to the second row. demo

And the rule doesn’t work as expected if the container has a height or min-height defined. demo


Even with CSS Grid Layout now widely available, Flexbox is still the better choice in some cases.

This covers all your requirements with clean and simple code:

article {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

section:last-child {
  flex-grow: 1;
}

section {
  /* flex-basis: auto <-- this is a default setting */
  margin-bottom: 10px;
  background-color: lightgreen;
}

body {
  margin: 0;
}
<article>
  <section>text text text</section>
  <section>text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text
    text text text text text text text text text text </section>
  <section>text text text text text text text text text text text text text text text text text text text text text text text text text text text</section>
  <section>text text text text text text text text text text text text text text text text text text text text text text text text text text text</section>
  <section>text text text text text text text text text text text text text text text text text text text text text text text text text text text</section>
</article>

Leave a Comment