87

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>
Robin Wieruch
  • 14,900
  • 10
  • 82
  • 107
CalAlt
  • 1,683
  • 2
  • 15
  • 29

3 Answers3

112

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; /* OR min-content*/
}

.grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-auto-rows: max-content; /* OR 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>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • 2
    Note that `grid-3` will take all parent height here. If you want `grid-3`'s height to fit content you can use [my answer](https://stackoverflow.com/a/49716873/1548895). – Vadim Ovchinnikov Apr 08 '18 at 11:22
67

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.

Community
  • 1
  • 1
Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
  • The solutions you proposed are good but then another problem arises: there is an extra space created by the margin which is not filled with content. How can I say to the grid system that I just need elements in columns? Maybe I should use flex here... Thanks – LucioB Sep 18 '19 at 09:00
  • @LucioB Sorry, didn't understand your question. Maybe it's better to ask a separate question with all details and examples and post the link here to me in comments. – Vadim Ovchinnikov Sep 18 '19 at 09:13
  • Based on what I'm seeing, LucioB is saying that with `align-items: start`, the bottom of the grid content ends where the content ends not where the grid cell ends, so then the next row below it has an extra size gap. – agm1984 Dec 11 '20 at 05:42
  • Every comment/answer like this on Stackoverflow gives me a powerful knowledge about programming. Thank you. – Babaktrad Sep 01 '23 at 18:43
11

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.

Goal Man
  • 171
  • 2
  • 6