Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

html

css

css-grid

I'm fiddling around with a CSS grid-based frontend and the following behaviour is required over and over and over again in different parts of the frontend:

  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.

So in the case I happen to need five rows, this does the trick:

.myGridForFiveRows
{
    display: grid;
    grid-template-rows: auto auto auto auto 1fr;
}

However, I'd really like a stylesheet that yields the correct behaviour for any given number of rows. I thought maybe I could somehow use repeat() to do this?

https://developer.mozilla.org/en-US/docs/Web/CSS/repeat

.myGrid
{
    display: grid;
    grid-template-rows: repeat(auto-fit, auto) 1fr;
}

I've been playing around with variants of repeat(auto-fit, auto) and repeat(auto-fill, auto), which unfortunately aren't legit CSS, while repeat(4, auto) or repeat(auto-fill, 30px) are.

Any idea? It's not something I can't circumvent, but it just so happens that "display n properly sized rows, then let the last element take up all the remaining space" is basically the default behaviour for all elements in my spec...

like image 626
Sascha Avatar asked Jan 19 '18 10:01

Sascha


1 Answers

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>
like image 152
Michael Benjamin Avatar answered Sep 17 '22 13:09

Michael Benjamin