How to make the items in the last row consume remaining space in CSS Grid?
Asked Answered
T

8

85

Is there a way to force all the items in the last row, of a grid, to fill the row, no matter how many they are?

I do not know the number of items that will be in the grid so I cannot target them directly. I tried to use grid-auto-flow: dense, but it is not really helping.

This is my question visualized: enter image description here:

div {
  margin:20px auto;
  width: 400px;
  background: #d8d8d8;
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(3, 1fr);
}
span {
  height: 50px;
  background: blue;
}
<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>  
</div>
 
Thorium answered 25/1, 2019 at 18:18 Comment(6)
@Padus Oh sorry! My bad :) Then he has to use tables right πŸ˜€ – Shaffer
@Shaffer Wouldn't recomment user tables either, this particular layout might be better done with Flexbox since OP can make the last item use the remaining space – Padus
@Padus What about creating two div's. And keeping the width of first div fixed and later dynamic. ☺️ – Shaffer
@Shaffer that might be even more work than just using flexbox – Padus
I would recommend you to use flexbox. – Lifetime
This is the main difference between css grid and css flex. Use flexbox for this . Flex can do this but grid can not unless you use hacky ways as mentioned in some of the answers. I read the article here developer.mozilla.org/en-US/docs/Web/CSS/… – Ardrey
D
35

This is totally possible with CSS grid by combining the CSS rules nth-child and nth-last-of-type. The only caveat is that the number of columns needs to be known in advance.

.grid {
    display: grid;
    grid-template-columns: auto auto auto;
    justify-items: start;
    grid-gap: 10px;
}

.grid div {
  border: 1px solid #ccc;
  width: 100%;
}

.grid > *:nth-child(3n-1) {
  justify-self: center;
  text-align: center;
}

.grid > *:nth-child(3n) {
  justify-self: end;
  text-align: right;
}

.grid > *:nth-child(3n-1):nth-last-of-type(1) {
  border-color: red;
  grid-column: span 2;
}

.grid > *:nth-child(3n-2):nth-last-of-type(1) {
  border-color: red;
  grid-column: span 3;
}
<div class="grid">
  <div>text</div>
  <div>TEXT</div>
  <div>text</div>
  <div>text</div>
  <div>TEXT</div>
  <div>text</div>
  <div>text</div>
  <div>TEXT</div>
</div>
Dissonant answered 28/5, 2019 at 9:31 Comment(8)
Thank you for your answer. Your solution would work only if we know that we have 3 columns in each row, and if, let's say, we have 6 columns, then we have to define the span 5 times by targetting the nth-child(6n-5) and so forth. – Thorium
Yes, as stated, but it fully works when you know the number of columns, so I believe this is an answer for your question.You could use scss to calculate these entries too, if the number of columns varies, such as when you use media queries. – Dissonant
Sorry for the misunderstanding, again, thank you for the time you put and answered the question, but this is NOT the answer :) If you please read the original post, I did not mention that we know the number of columns and if that is what you assumed, then I can state that it was NOT a predefined value, we do NOT know the number of columns. To is more clear, this is for a template we are making on an eCommerce platform, we have used Flex instead(in the meantime) but the whole idea is that the CSS is not dependent on the number of the column, at least not to the extent your answer is stating. – Thorium
Your css shows "grid-template-columns: repeat(3, 1fr)" and your request is how to make the items fill the remaining space, no matter how many ITEMS there are. I answered that. If you need to ask a further question about how do you do this in a scenario where you don't know how many columns there are, please do so. – Dissonant
I am really not trying to make arguments, and I truly thank you for the answer, but it is not the right answer to my question, sorry about that! – Thorium
This isn't really an answer to the question, which clearly states in the accompanying diagram "we do not know the number of items". So an answer that works only if you know ahead of time the only thing OP won't know ahead of time is, with all due respect, pretty much useless to OP. – Raeannraeburn
confusing "items" with "columns" – Dissonant
The original post declared a 3 columns grid. If the original post declared "auto-fit" and "given an arbitrary # of columns.." then the argument would stand. But this answers the original question perfectly in the context. Thanks @Dissonant this worked perfectly for my use-case! (I actually modified to 6 columns so I can have the last-two span 50% of the grid) – Kurdish
P
24

I don't think CSS Grid is the best option for the layout you're trying to build, at least not if it's going to be dynamic and you don't really know how many items will be on the container all the time. Flexbox is actually better for one-dimensional layouts; it might be a little harder to keep everything the exact same size and using all of the available space exactly as you need it, but at the end this type of cases is what Flexbox is built for.

And of course you can make use of 100% width by using few calculations on CSS as well.

CSS Grid might be better to keep rows AND columns aligned, but this is a different case.

.container {
  display: flex;
  flex-wrap: wrap;
  box-sizing: border-box;
}

.flex-item {
  width: 30%;
  border: 1px solid #000;
  flex-grow: 1;
  min-height: 120px;
  box-sizing: border-box;
  margin: 0 5px 10px;
  justify-content: space-between;
  text-align: center;
}
<div class="container">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
</div>
Padus answered 25/1, 2019 at 18:31 Comment(5)
Thank you for your answer. I am using the Flexbox for the fallback. One (not the only) reason why I am looking into grids is to use "gap" and other features that come with it. For example, even though gap can be simulated by the margin, but since we do not know the number of items in the last row, getting rid of the side gaps (on the side of the container) will require extra code. – Thorium
@Ogdila no problem! Its unfortunate, it just seems it is not possible as of now; I actually just found this other question with the same issue and looks like CSS Grid is not able to achieve this https://mcmap.net/q/243958/-how-to-make-css-grid-last-row-to-take-up-remaining-space/8437694 – Padus
According to specs you can just say e.g. gap: 0.25rem just fine with Flexbox, too. Unfortunately, only Firefox and recent Chrome has proper support for this. Safari is still (2021 Q1) failing to support this: caniuse.com/flexbox-gap – Stunning
@MikkoRantalainen that's cool, hopefully it gets more widely adopted, would help a lot with designs like these – Padus
Good news, Safari 14.1 supports gap on flexbox. Just need to wait for the older versions to vanish now! – Buccaneer
L
10

For those looking for an answer to this for just the last element, you can try grid-column: 1 / -1; or col-span-full if you are using tailwindcss.

div {
  margin:20px auto;
  width: 400px;
  background: #d8d8d8;
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(3, 1fr);
}
span {
  height: 50px;
  background: blue;
}
div > span:last-of-type {
  grid-column: 1 / -1;
}
<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>  
</div>
Loreanloredana answered 20/7, 2022 at 22:51 Comment(1)
Sorry for necroposting but your solution works only when you have one item in the last row. Although according to the OP question it may have two or three items as well. – Flogging
P
3

This isn't possible in the current version (Level 1) of CSS Grid. However, it's not too complicated with flexbox.

You wrote in a comment:

I am using the Flexbox for the fallback. One (not the only) reason why I am looking into grids is to use "gap" and other features that come with it. For example, even though gap can be simulated by the margin, but since we do not know the number of items in the last row, getting rid of the side gaps (on the side of the container) will require extra code.

You're right: The grip-gap feature in CSS Grid is quite handy. However, you can emulate the behavior using margins – without much complexity – in flexbox, as well.

div {
  display: flex;
  flex-wrap: wrap;
  padding: 0px 0px 5px 5px;
  margin: 20px auto;
  width: 400px;
  background: #d8d8d8;

  }
span {
  flex: 1 0 30%;
  height: 50px;
  margin-top: 5px;
  margin-right: 5px;
  background: blue;
}
<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div>
  <span></span>
  <span></span>
  <span></span>
</div>

<div>
  <span></span>
  <span></span>
</div>

<div>
  <span></span>
</div>
Prismatoid answered 25/1, 2019 at 23:14 Comment(2)
Now we have gap property in flex box too! Awesome! – Rhapsody
Excellent example! – Decision
A
3

You can try selecting only the excedent item with nth-child and last-of-type selectors and finally spaning that last item to the total number of columns in the grid (automatically done with grid-column: 1 / -1)

.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 8px;
  row-gap: 8px;
}

.grid-item {
  background: lightblue;
}

.grid-item:nth-child(2n-1):last-of-type {
  background: coral;
  grid-column: 1 / -1;
}
<div class="grid">
  <div class="grid-item">Item 1</div>
  <div class="grid-item">Item 2</div>
  <div class="grid-item">Item 3</div>
  <div class="grid-item">Item 4</div>
  <div class="grid-item">Item 5</div>
</div>
Abiotic answered 10/1, 2023 at 8:51 Comment(0)
B
0

Example css grid with last items 3/3, 3/2, 3/1

.grid {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    grid-template-rows: 1fr;
    grid-auto-rows: 50px;
    grid-template-rows: 50px;
    grid-gap: 25px;
}
.grid.yellow>div{
    background-color: rgb(233, 216, 68);
}
.grid.blue>div{
    background-color: rgb(73, 73, 216);
}
.grid.green>div{
    background-color: rgb(53, 170, 53);
}
.grid>div {
    grid-column: span 4/auto;
}
.grid>div:nth-child(3n - 1):nth-last-of-type(1), 
.grid>div:nth-child(3n - 2):nth-last-of-type(2) {
    grid-column: span 6/auto;
}
.grid>div:last-child:nth-child(3n - 2){
    grid-column: span 12/auto;
}
h2{
    text-align: center;
}
<h2>Grid last items 3</h2>
  <div class="grid yellow">
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
  </div>
  <hr>
  <h2>Grid last items 2</h2>
  <div class="grid blue">
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
  </div>
  <hr>
  <h2>Grid last items 1</h2>
  <div class="grid green">
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
  </div>
Brook answered 11/6 at 8:7 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center. – Guesstimate
N
-2

You can use the grid-column-end: -1 on the element that you want to be in the last col in the grid even if you don't know the number of cols in your grid

Nichols answered 15/4 at 8:15 Comment(0)
S
-4

I have found the answer to your question I have reproduced it here: https://jsfiddle.net/nmcobalt/dg3mutwv/13/

In order to do the css less complicate and solve this complex issue, it is recommended to use SCSS* instead of plain css.

In SCSS file you have to use the css selector nth:last-child with iteration calculating childs based on modulo function and the constant factor of the 3 columns.

@mixin setLastChildFluid{
  @for $i from 1 through 10 {    
    $span: 3;
    @if $i % 3 == 0{
      $span: 1;
    } @else if $i % 3 == 1{
      $span: 3;
    } @else if $i % 3 == 2{
      $span: 2;
    } 
    @if $span == 2 {
      span:nth-child(#{$i - 1}){
        &:nth-last-child(2){
          grid-column-end:span 1;
          position:relative;
          bottom:0;
          width:calc(150% + 5px);
          left:0;    
        }
      }
      span:nth-child(#{$i}){
        &:nth-last-child(1){
          grid-column-start:2;
          position:relative;
          bottom:0;
          width:calc(150% + 5px);
          left:calc(50% + 5px);
        }
      }
      
    } @else {
      span:nth-child(#{$i}){
        &:last-child{
            grid-column-end:span #{$span};          
        }
      }
    }
    
  }
}
div {
  position:relative;
  margin:20px auto;
  width: 400px;
  background: #d8d8d8;
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(3, 1fr);
  
  @include setLastChildFluid;
}
span {
  height: 50px;
  background: blue;
  color:yellow;
}

and the following html markup; I have done two different examples (wrapped by div) to reproduce your query:

<div>
  <span>1</span>
  <span>2</span>
  <span>3</span>
  <span>4</span>
  <span>5</span>
  <span>6</span>
  <span>7</span>
  <span>8</span>
</div>
<div>
  <span>1</span>
  <span>2</span>
  <span>3</span>
  <span>4</span>
  <span>5</span>
  <span>6</span>
  <span>7</span>
</div>

Change the number of divs in order to see the fluid result.

*SASS is a preprocessor scripting language that is interpreted or compiled into Cascading Style Sheets (CSS). Learn more here: https://sass-lang.com/guide

Salaried answered 5/12, 2019 at 15:13 Comment(2)
Yes I know, but with scss is become much simpler in a very complex thing. You can always convert scss to css with online tool. – Salaried
I have to admit it is more simpler in a complex manner. But just saying as he didn't really ask about scss, he might not know what scss is. You should at least explain a bit about scss to make it more convenient then just search for an answer. – Backdate

© 2022 - 2024 β€” McMap. All rights reserved.