CSS Grid - Auto height rows, sizing to content

CssCss Grid

Css Problem Overview


I have two grids nested within a grid. Unfortunately the right nested grid .grid-3 sets the height of the rows so that both the left and right grid are the same height, the extra space is shared among the divs with the class .right. How can I set the rows of the right nested grid to adjust to the size of the content, so they are the same height as the left nested rows?

div {
  border: 1px dotted black;
}
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows auto;
}

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

.left {
  background-color: red;
}
 
.right {
  background-color: green;
}

<div class="grid-2">
      <div class="grid-2">
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
     </div>
     <div class="grid-3">
         <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
     </div>
</div>

Css Solutions


Solution 1 - Css

You can try minmax(min-content, max-content) ref

div {
  border: 1px dotted black;
}
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: minmax(min-content, max-content);
}

.grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-auto-rows: minmax(min-content, max-content);
}

.left {
  background-color: red;
}
 
.right {
  background-color: green;
}

<div class="grid-2">
      <div class="grid-2">
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
     </div>
     <div class="grid-3">
         <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
     </div>
</div>

You can also use only max-content or min-content

div {
  border: 1px dotted black;
}
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: max-content; /* min-content*/
}

.grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-auto-rows: max-content; /* min-content*/
}

.left {
  background-color: red;
}
 
.right {
  background-color: green;
}

<div class="grid-2">
      <div class="grid-2">
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
     </div>
     <div class="grid-3">
         <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
     </div>
</div>

Solution 2 - Css

By default grid items stretch to all grid cell area. So you have this options here if you want grid's height to fit content:

  • Set alignment for all items using align-items for grid container (default value is align-items: stretch). So just set align-items: start for grid-2. Demo:

div {
  border: 1px dotted black;
}

.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  align-items: start;
}

.grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

.left {
  background-color: red;
}
 
.right {
  background-color: green;
}

<div class="grid-2">
      <div class="grid-2">
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
     </div>
     <div class="grid-3">
         <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
     </div>
</div>

  • Set alignment for grid items individually using align-self (default value is align-self: stretch). So just set align-self: start for grid-3. Demo:

div {
  border: 1px dotted black;
}

.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}

.grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  align-self: start;
}

.left {
  background-color: red;
}
 
.right {
  background-color: green;
}

<div class="grid-2">
      <div class="grid-2">
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
     </div>
     <div class="grid-3">
         <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
     </div>
</div>

  • Set alignment for grid items individually using margin property with auto values. Auto margins for grid cell take all available space in any direction. So just set margin-bottom: auto for grid-3. Demo:

div {
  border: 1px dotted black;
}

.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}

.grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  margin-bottom: auto;
}

.left {
  background-color: red;
}
 
.right {
  background-color: green;
}

<div class="grid-2">
      <div class="grid-2">
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
        <div class="left">L</div>
     </div>
     <div class="grid-3">
         <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
        <div class="right">R</div>
     </div>
</div>

If you want right grid to take all parent vertical space but make its cells to fit content use this answer.

Solution 3 - Css

You can also try grid-auto-rows: fit-content(1em);. Of course, use whatever sizing makes sense for you. I also tried the approach described by Temani (minmax(min-content, max-content)) and the results were identical when rendering my HTML.

According to Elad Schechter - Medium,

> The fit-content function accepts one param, the maximum value. ... The fit-content() function is similar to using the minmax() function, with a minimum value of 0. One key difference: The minmax() is more likely to occupy the max space allowed, while the fit-content does not occupy any more space than necessary.

Your needs will determine whether fit-content is more appropriate than using minmax and vice-versa.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCalAltView Question on Stackoverflow
Solution 1 - CssTemani AfifView Answer on Stackoverflow
Solution 2 - CssVadim OvchinnikovView Answer on Stackoverflow
Solution 3 - CssGoal ManView Answer on Stackoverflow