101

I am using CSS grid to layout some items like this...

#container {
  display: grid;
  grid-template-columns: 16.666% 16.666% 16.666% 16.666% 16.666% 16.666%;
}

.item {
  background: teal;
  color: white;
  padding: 20px;
  margin: 10px;
}
<div id="container">
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
</div>

How can I get the last row to be centered instead of left aligned? I can't guarantee the number of items so want to make the layout look right for any number of items.

Is this something I should be using flexbox for instead? Or are CSS grids a suitable use?

3
  • Helpful Article: zellwk.com/blog/responsive-grid-system Commented Sep 18, 2017 at 10:52
  • 1
    No...I don't think so unless you know the number of remaining items. You could then add a whole bunch of CSS rules to adjust the column-start. But,,,what is supposed to happen when there is an odd number of left over items? Commented Sep 18, 2017 at 11:08
  • @fightstarr20 I don't think css grids are meant for that - its a 2D layout. In the example you have a layout that flows in one dimension - so use flexbox... Commented Sep 18, 2017 at 11:57

12 Answers 12

109

CSS Grid isn't suited for alignment across an entire row because of crisscrossing tracks blocking the way. Here's a detailed explanation:

As an alternative, use flexbox with justify-content: center.

This packs all items in the horizontal center of the row. Then your margins push them apart.

On fully-filled rows, justify-content will have no effect since there's no free space for it to work.

On rows with free space (in your case, only the last row), the items are centered.

#container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.item {
  flex: 0 0 calc(16.66% - 20px);
  background: teal;
  color: white;
  padding: 20px;
  margin: 10px;
}

* {
  box-sizing: border-box;
}
<div id="container">
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

Works great, thanks so much!
59

Found a great article on how to Control Leftover Grid Items with Pseudo-selectors

.grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-gap: 20px;
  margin: 20px;
  padding: 20px;  
}
.item {
  grid-column: span 2;
  background: #AB47BC;
  padding: 20px;
}

/* Dealing with 2 orphan items */

.item:last-child:nth-child(3n - 1) {
  grid-column-end: -2;
}

.item:nth-last-child(2):nth-child(3n + 1) {
  grid-column-end: 4;
}

/* Dealing with single orphan */

.item:last-child:nth-child(3n - 2) {
  grid-column-end: 5;
}
<div class="wrapper">
    <div class="grid grid--1">
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>

    <div class="grid grid--2">
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>
</div>

Comments

14

That defeats the purpose of a grid system. A grid is a 2 dimensional array where everything has an X and Y value, like a spreadsheet.

Yes, you want a system where the items wrap. Flexbox fits the bill here because of flex-wrap.

#container {
  padding: 10px;
  width: calc((100px + (10px * 2)) * 4); /* item width + padding on either side times number of items */
  display: flex;
  flex-wrap: wrap;
  background: blue;
  margin: 10px;
}

#container div {
  width: 100px;
  height: 100px;
  flex-grow: 1;
  background: red;
  margin: 10px;
}

https://jsfiddle.net/0c0hzh8t/

This makes the children occupy all the available space, which if the row is full will be none and it'll be its standard size.

If you want the container to be sized automatically, then remove the width property and the container and its items will be resized automatically. It's just as well, but I assume you want to define the amount of items in a row.

2 Comments

It's a good explanation of why grid layout doesn't fit the OP's requirements. It really should have higher rating!
This is why it shouldn't be Grid vs Flexbox. Both have their use-cases.
7

There is no specific property for making the last row behave differently than the previous ones.

Still, based on the fact that you define a set width that match n items within the viewport's width, you can use Flexbox and its justify-content property.

Set it to center and it will center the last row for any number of items.

Stack snippet

html, body {
  margin: 0;
}

#container {
  display: flex;
  flex-wrap: wrap;                  /*  allow items to wrap  */
  justify-content: center;          /*  horizontally center items  */
}

.item {
  flex-basis: calc(16.666% - 20px); /*  subtract the margin from the width  */
  background: teal;
  color: white;
  padding: 20px;
  margin: 10px;
  box-sizing: border-box;           /*  make padding be included in the set width  */
}
<div id="container">
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
</div>

Comments

5

This should center any item inside row without using flex

.center-item {
    grid-column: 1 / -1;
}

2 Comments

This seems to stretch a row to 100% width. As well, in a dynamic situation, you don't know which items are in the last row.
works perfectly when the number of items is fixed and is responsive too
3

for grid item

grid-column: 1/-1;
margin: 0 auto;

Comments

2

I really wanted a solution that wouldn't produce outside margins on the elements, instead using gap. I just multiplied the row gaps, then divided by how many items I want on the row - then subtracted from the width. Voila.

I realize it's not CSS grid, but flexbox is actually a better use case for staggered rows.

:root {
  --marginXBase: 10px;
  --marginYBase: 10px;
}
.container {
  display: flex;
  flex-flow: row wrap;
  justify-content: center;
  align-items: stretch;
  align-content: flex-start;
  gap: var(--marginXBase) var(--marginYBase);
  outline: 1px solid black;
}
.item {
  background-color: blue;
  min-height: 15px;
  /* default to 3up */
  flex: 0 0 calc(33.33% - (var(--marginXBase) * 2) / 3);
}
.x-2up {
  background-color: green;
  flex: 0 0 calc(50% - (var(--marginXBase) * 1) / 2);
}
.x-4up {
  background-color: red;
  flex: 0 0 calc(25% - (var(--marginXBase) * 3) / 4);
}
<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

<br>

<div class="container">
  <div class="item x-2up"></div>
  <div class="item x-2up"></div>
  <div class="item x-2up"></div>
</div>

<br>

<div class="container">
  <div class="item x-4up"></div>
  <div class="item x-4up"></div>
  <div class="item x-4up"></div>
  <div class="item x-4up"></div>
  <div class="item x-4up"></div>
  <div class="item x-4up"></div>
  <div class="item x-4up"></div>
</div>

1 Comment

Not sure why more people have not up voted this, it works fairly well and is a much better solution than those with more up votes
2

This works perfectly for example for a 3-column layout with a seventh item:

enter .parent {
display:grid;
grid-template-columns:repeat(3,1fr);
gap:2rem; }


.child:last-child {
justify-self: center;
grid-column-start: span 3;
width: calc(32.9% - 1rem); }

Comments

1

I've just spent the last few days working on a solution for this, it actaully centers the last column using grid. Here's a full explanation https://koalawidgets.com/how-to-center-elements-on-the-last-row-in-css-grid/

It's basically based on Taras' response, but I made it work for various layouts, not only 3 column layouts.

Here's the code

html{background:#111;color:#fff;padding:1rem;}
*{padding:0;margin:0;}
:root{
  --min-width:200px;
  --grid-gap:20px;
  /* Remember to update these values in the container queries as well */
}
.wrapper{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(calc((var(--min-width) - var(--grid-gap))/2),calc((100% - var(--grid-gap)) / 2)),1fr));
  grid-gap: var(--grid-gap);
  outline:2px solid lightblue;
  max-width:calc(var(--min-width)*6 + var(--grid-gap)*5);
  container: grid-wrapper / inline-size;
}

.item{
  outline:2px solid pink;
  padding:1rem;
  grid-column: span 2;
}

/* 2 Column Layouts */
@container grid-wrapper (min-width: calc(200px*2 + 20px)) and (max-width: calc(200px*3 + 20px*2)) {
  /* Dealing with 1 orphan item */
  .item:last-child:nth-child(2n + 1){
    grid-column-end: 4;
  }
}

/* 3 Column Layouts */
@container grid-wrapper (min-width: calc(200px*3 + 20px*2)) and (max-width: calc(200px*4 + 20px*3 - 1px)) {
  /* Dealing with 1 orphan item */
  .item:last-child:nth-child(3n + 1){
    grid-column-end: 5;
  }
  /* Dealing with 2 orphan items */
  .item:nth-last-child(2):nth-child(3n + 1) {
    grid-column-end: 4;
  }
}

/* 4 Column Layouts */
@container grid-wrapper (min-width: calc(200px*4 + 20px*3)) and (max-width: calc(200px*5 + 20px*4 - 1px)) {
  /* Dealing with 1 orphan item */
  .item:last-child:nth-child(4n + 1){
    grid-column-end: 6;
  }
  /* Dealing with 2 orphan items */
  .item:nth-last-child(2):nth-child(4n + 1){
    grid-column-end: 5;
  }
  /* Dealing with 3 orphan items */
  .item:nth-last-child(3):nth-child(4n + 1){
    grid-column-end: 4;
  }
}

/* 5 Column Layouts */
@container grid-wrapper (min-width: calc(200px*5 + 20px*4)) and (max-width: calc(200px*6 + 20px*5 - 1px)) {
  /* Dealing with 1 orphan item */
  .item:last-child:nth-child(5n + 1){
    grid-column-end: 7;
  }
  /* Dealing with 2 orphan items */
  .item:nth-last-child(2):nth-child(5n + 1){
    grid-column-end: 6;
  }
  /* Dealing with 3 orphan items */
  .item:nth-last-child(3):nth-child(5n + 1){
    grid-column-end: 5;
  }
  /* Dealing with 4 orphan items */
  .item:nth-last-child(4):nth-child(5n + 1){
    grid-column-end: 4;
  }
}

/* 6 Column Layouts */
@container grid-wrapper (min-width: calc(200px*6 + 20px*5)) and (max-width: calc(200px*7 + 20px*6 - 1px)) {
  /* Dealing with 1 orphan item */
  .item:last-child:nth-child(6n + 1){
    grid-column-end: 8;
  }
  /* Dealing with 2 orphan items */
  .item:nth-last-child(2):nth-child(6n + 1){
    grid-column-end: 7;
  }
  /* Dealing with 3 orphan items */
  .item:nth-last-child(3):nth-child(6n + 1){
    grid-column-end: 6;
  }
  /* Dealing with 4 orphan items */
  .item:nth-last-child(4):nth-child(6n + 1){
    grid-column-end: 5;
  }
  /* Dealing with 5 orphan items */
  .item:nth-last-child(5):nth-child(6n + 1){
    grid-column-end: 4;
  }
}
<div class="wrapper">
  <div class="item"><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p></div>
  <div class="item"><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
    <p>Longer.</p>
  </div>
  <div class="item"><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p></div>
  <div class="item"><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p></div>
  <div class="item"><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p></div>
  <div class="item"><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p></div>
  <div class="item"><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p></div>
  <div class="item"><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p></div>
  <div class="item"><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p></div>
  <div class="item"><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p></div>
  <div class="item"><p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p></div>
</div>

Comments

-1

Codepen

  <div class="grid grid-cols-3 justify-items-center gap-2">
    <div class="w-5">1</div>
    <div class="w-5">2</div>
    <div class="w-5">3</div>
    <div class="w-5">4</div>
    <div class="w-5">5</div>
    <div class="w-5">6</div> 
    <div class="w-5">7</div>
    <div class="w-5">8</div>
    <div class="w-5">9</div>
    <div class="col-span-3">0</div>
 </div>
.col-span-3 {
  grid-column: span 3 / span 3;
}

.grid {
  display: grid;
}

.w-5 {
  width: 1.25rem;
}

.grid-cols-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.justify-items-center {
  justify-items: center;
}

.gap-2 {
  gap: 0.5rem;
}

3 Comments

This doesn't fix the problem if the amount of containers is not fixed
item:last-child { grid-column: span 3 / span 3; }
That still doesn't fix the problem. For example, it will look fine with 10 elements since you want to center the last one. It wont look good with 11 because you will have the 10th element alone in the left column and the last one under that one in the center. jsfiddle.net/juh7stvp/14
-3

I didn't work much on grids but as far as I know if you want to use Flex-box use this code.

#container {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
 }

.item {
  flex: 1;
  flex-basis: 16.66%;
  background: teal;
  color: white;
  padding: 20px;
  margin: 10px;
}
<div id="container">
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
</div>

Appreciate if useful. Ignore if not.

Comments

-4

This is my solution (as of April 23, 2018) for writing HTML emails:

#wrapper {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-row-gap: 0;
  grid-column-gap: 15px;
  padding: 15px 15px 0 15px;
}

.item {
  border: 1px solid #000;
  height: 200px;
  margin-bottom: 15px;
}
<div style="width: 100%; margin: 0 auto; text-align: center; vertical-align: middle;">
  <div style="overflow: auto; height: 400px; margin-top: 15px;">
    <div style="position: relative">
      <div id="wrapper">
        <div class="item"><div>Item 1</div></div>
        <div class="item"><div>Item 2</div></div>
        <div class="item"><div>Item 3</div></div>
        <div class="item"><div>Item 4</div></div>
        <div class="item"><div>Item 5</div></div>
        <div class="item"><div>Item 6</div></div>
        <div class="item"><div>Item 7</div></div>
        <div class="item"><div>Item 8</div></div>
      </div>
      <div style="position: absolute; bottom: -30px; text-align: center; margin: 0 auto; width: 100%;">
        <div style="background-color: #defabc; width: 300px; margin: 0 auto; text-align: center; cursor: pointer;">
          <span style="color: #000;">See all items</span>
        </div>
      </div>
    </div>
  </div>
</div>

What it does is, you're able to position items to the center at the very bottom of the grid wrapper. Again, like all other solutions, you can't put something inside a grid wrapper to be center-aligned in the very last row.

But at least this is a good alternative solution as a workaround.

2 Comments

Are you out of your mind using this for HTML Email? caniemail.com/features/css-display-grid
When I was working on it, it was back in 2016, when it was working for the client I worked with who wanted this in their HTML campaign. At the time, I was just a recently new hire with no experience, and I had to struggle and figure things out. And yes, I am aware of what I wrote no longer applies to HTML emails nowadays. The CSS display grid you linked to now only works for nearly 50% of the email clients.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.