Why does a different row height in the 4th row change the row height distribution among the first three rows?

2 weeks ago 20
ARTICLE AD BOX

The issue

My logic was: to fit the minimal content, the first row can shrink to the height of the item in p, likewise the second can shrink to the height of the item in o. Only the third needs to be big enough to fit the video (item in v) and thus scales also the item in t [...] appropriately.

Sounds plausible. But ...

However, this is not what happens. Instead, the video-height seems to be divided by three for the first three rows.

If you look more carefully, I think you'll find that the first three rows do not have equal height. That might be clearer if you give the first two right-hand items align-self: end, so that you can better visualize where the bottoms of the first two rows are.

Solutions

can I achieve the height-distribution of the first three rows like in the second snippet, but not scaling the last row with 1fr

Option 1: size the third row with 1fr

This seems pretty appropriate to me, because it is this row, not the last, for which min-content doesn't suffice to define the height (because there is no grid item confined to this row):

grid-template-rows: min-content min-content 1fr min-content;

This expresses exactly what you seem to want. The fixed-height "preview", "optional", and "metadata" items establish the heights for their rows; the "metadata" and "video" items together establish the overall height of the grid, and the third row soaks up however much space is needed to make that work out.

Complete example:

html, body { height: 100vh; max-height: 100vh; margin: 0px; } /* Grid-Container */ #container { display:grid; grid-template-areas: "v p" "v o" "v t" "m t"; grid-template-columns: 1fr min-content; grid-template-rows: min-content min-content 1fr min-content; gap: 4px; width:100%; } /* Grid-Items */ div.grid-item { border-color: black; border-width: 2px; border-style: solid; position: relative; } #video { background-color: green; height: 180px; grid-area: v; } #metadata { background-color: yellow; height: 30px; grid-area: m; } #previewSelect { background-color: red; height:30px; grid-area: p; } #transcript { background-color: blue; align-self: stretch; grid-area: t; } #optional { height: 30px; grid-area: o; } <html> <body> <div id="container" class="l1"> <div id="video" class="grid-item">Video</div> <div id="metadata" class="grid-item">Metadata</div> <div id="previewSelect" class="grid-item">Preview-Select</div> <div id="transcript" class="grid-item">Transcript</div> <div id="optional" class="grid-item">Optional</div> </div> </body> </html>

Option 2: size the first two rows explicitly

If you give explicit sizes for the first two rows and optionally to the last, but not to the third, then the extra space will all go to the third row. In this case, you need the content height (which you're already specifying on the items) plus border size:

grid-template-rows: 34px 34px min-content min-content;

That doesn't use flex sizing anywhere.

Explanation

And how is the difference in the outcome between the two snippets explainable?

The track-sizing computations are documented in the W3C's (draft) specification for CSS Grid. To save you some time if you choose to read that, min-content is an "intrinsic" sizing function, 1fr is a "flexible" sizing function, and 34px is a "fixed" sizing function. These different kinds of sizing functions have qualitatively different effects on track size computations. Furthermore, it makes a difference that your third row has no items to establish a base size or growth limit for it, as all items that cover it span multiple rows.

Additionally, grid items' alignment and justification rules have nothing to do with track sizing. They only affect item positioning (and maybe sizing) after the grid is computed.

The details are complicated, but, what happens when you use min-content for all the rows is that the grid rows are initially computed to have base sizes 34px, 34px, 0, and 34px, based on the minimum content height of the items within, then the additional space needed to accommodate the video is split evenly among the three rows it spans.

When you instead give the third row flex sizing or give the first two fixed sizing, then the extra space for the video goes preferentially to the third row.

I haven't fully deciphered why giving only the last row flex sizing causes the extra space for the video to go preferentially to the third row in your case, but the sizing algorithm does have provisions for items that span flexible tracks. In any case, you didn't want to do that, and it doesn't seem sensible anyway, so I'm going to punt on the full elucidation.

Read Entire Article