How to center elements on the last row in CSS Grid?

80
January 01, 2020, at 1:40 PM

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?

Answer 1

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

  • Aligning grid items across the entire row/column (like flex items can)

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>

Answer 2

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.

Answer 3

There is no specific property for making the last row behave differently than the previous one's.

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>

Answer 4

This should center any item inside row without using flex

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

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.

Answer 6

This is my solution (as of April 23, 2018):

#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.

READ ALSO
Gatsby 1 Class Component

Gatsby 1 Class Component

I'm trying to understand the logic of this component called AppMounted in a layout (Gatsby 1)

104
Responsive Menu with Semantic UI React

Responsive Menu with Semantic UI React

With Semantic UI React I'm having trouble in creating a responsive navigation menu

125
How prevent multiple login with same login credentials in jwt authentication WordPress?

How prevent multiple login with same login credentials in jwt authentication WordPress?

What to do when authentication done for outside the wp environment eg Android or desktop app

88
S3 stream wrapper directory listing. Script is failing without making it past this point. Cant find out why

S3 stream wrapper directory listing. Script is failing without making it past this point. Cant find out why

Trying to understand why my previously tested and working code is failing when trying to test in another dev location(virtual test machine to physical test machine)Using PHP stream wrapper library and AWS PHP SDK to do directory listing and move each file name into an array being modified

77