9

With a flex container and flex-wrap: wrap set you can align overflowing items to the center using justify-content: center.

Is there a way to achieve the same behaviour for overflowing grid items using CSS grid?

I've created a pen showing the desired flex behavior

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

.container-flex .item {
  width: 33.33%;
  background: green;
  border: 1px solid;
}

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

.container-grid .item {
  background: red;
  border: 1px solid;
}

* {
  box-sizing: border-box;
}
<h3>Flex</h3>
<div class="container-flex">
  <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>

<h3>Grid</h3>
<div class="container-grid">
  <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>

https://codepen.io/JoeHastings/pen/PeEjjR

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
HastingsDirect
  • 628
  • 1
  • 9
  • 17
  • in a generic way I would say no as this not what grid is done for ... but for particular case we can always find workarounds – Temani Afif May 08 '18 at 13:09
  • Possible duplicate of [Centering in CSS Grid](https://stackoverflow.com/questions/45536537/centering-in-css-grid) – johnny May 08 '18 at 14:07
  • 2
    @johnny I don't think it's a duplicate, that question is about centring text/items inside grid cells which is pretty different to handling wrapping and centring of grid items themselves – HastingsDirect May 08 '18 at 15:00
  • I retracted it. – johnny May 08 '18 at 15:02
  • What make you think Flexbox and Grid can do the same? If, then why do we need both, one would be fine. They are two completely different things, though share some features, and some not. And we need both, as there is no single solution that can handle everything. – Asons May 08 '18 at 17:27
  • @LGSon I know they are different, but as they are both display based properties they can achieve very similar results in many cases. I wondered if I may have been missing a property or something obvious as it felt more like a grid layout thing, as my desired behaviour was across two axis, and not just a single row or column. Setting percentage widths at different break points and having flex wrap does not feel to me exactly what flex was designed to do – HastingsDirect May 15 '18 at 16:12
  • @JoeHastings The issue where one need to _"use percentage widths at different break points"_, is more related to the box model itself than a Flexbox issue. For some of those things features were added to CSS Grid, and might also be an upgrade to an upcoming Flexbox v.2. – Asons May 15 '18 at 17:00

3 Answers3

11

Flex and Grid are different animals, so a behavior that's simple in flex may not translate well to grid.

A flex item can center across the container because flex layout works with flex lines. A flex line is a non-intersecting row or column.

When a flex item is asked to center in the flex line, it has access to the available space on the entire line. This makes centering simple and easy.

In grid layout, however, there are tracks, which are intersecting rows and columns. For example, in your layout there are three columns. These columns cut across the row, dividing it into three separate sections, and grid items are confined to a section.

Therefore, a grid item cannot automatically be centered on a row using keyword alignment properties (such as justify-content or justify-self) because the intersecting tracks restrict movement.

It is possible to make a grid area span the entire row/column, which then clears the way across the entire track, allowing a grid item to be centered horizontally (justify-content: center) or vertically (align-self: center), but this behavior must be explicitly defined.

For the grid item to be centered across the row in a dynamic layout the container would need to have only one column, or the item would need to be explicitly moved to the center using something like line-based placement. Otherwise, use flexbox.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 1
    So we are still doomed when we want to center the items but have each row be the same height which is the tallest item's height within the grid - since flex can do the centering well but it does do the row height, grid can do row height but cannot do centering – Huangism Nov 06 '20 at 00:51
1

Not the way you want with flex. You have to be precise with CSS-Grid,

<h3>Grid</h3>
<div class="container-grid">
    <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-mid">item</div>
</div>
.container-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
}
    .item {
        background: red;
        border: 1px solid;
    }
    .item-mid{
        background:purple;
        grid-column:2/1;
    }

Also, look here,

Centering in CSS Grid

(this is not wrapping, however)

johnny
  • 19,272
  • 52
  • 157
  • 259
  • 2
    It surprises me grid can't handle this, it makes it a bit annoying when you don't know how many items there are going to be but you want any overflowing items to be centred (without getting javascript involved adding classes) seems like flex and percentage widths is the best option for this case – HastingsDirect May 08 '18 at 15:06
  • You can use flex in the grid or create a nested grid. I think the intention is to use flex for that because of the single axis and justify-content. – johnny May 08 '18 at 15:12
0

Late to this party. But at least in 3 grid row scenarios like this you can use a mixture of :nth-of-type and :last-of-type to target the trailing item and place it in the column. Kind of piggy backing off of the answer above you get:

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

    .item {
        background: red;
        border: 1px solid;
    }
        /* target the last item, if its the only one in the row */
        .item:last-of-type:nth-of-type(3n+1) {
            background:purple;
            grid-column:2;
        }

This, unfortunately, doesn't scale out super well to any other row count due to the problems listed in the above answers, but maybe will help someone.

Andrew Herder
  • 113
  • 1
  • 9