Selecting the last grid row in CSS
Recently I had the need to select the last row of elements in a grid using CSS. The selector needed to be able to handle an arbitrary total number of elements in the grid; in other words, in a grid with x columns, there could be 0 to x elements in the last row.
With a fixed or predictable number of elements in the grid, this would be quite
straightforward. You can select on :nth-last-child(-n+x)
, with x being
the known number of elements in the last row. If this was in a table, then you
could simply select tr:last-child
to get the last row.
Similarly, selecting the first row of elements can be achieved quite directly
with :nth-child(-n+x)
. This will select the first row of elements in a grid
with x columns, and it doesn’t matter if there are not enough elements to
fill the first row.
Mozilla Developer Network has great explanations of the :nth- child and :nth-last- child pseudo classes.
It only gets tricky when you want to select the last row of elements and there’s an arbitrary number of them.
The way to achieve it in CSS is (again where x is the number of columns):
- Select every xth element to get the first element of each row.
- Select the x last elements to limit that to the last row (you now have the first element of the last row).
- Use a sibling selector to get the elements after that element (which is the rest of the last row).
If we’re using an ul
with a li
for each element in the grid, then the above
looks like this. First select every xth element:
li:nth-child(xn+1)
Then limit that to the x last elements:
li:nth-child(xn+1):nth-last-child(-n+x)
Now we’ve got the first element of the last row. We also want to select siblings of that to get the rest of the row (remember that the sibling selector only applies to elements after the specified sibling):
li:nth-child(xn+1):nth-last-child(-n+x),
li:nth-child(xn+1):nth-last-child(-n+x) ~ li
Now we can style the elements in the last row however we want. In my case I wanted to remove the margin underneath the last row to prevent extra spacing below the grid (if you’re using flexbox then you can probably avoid the need for this with [align-content](https://css-tricks.com/almanac/properties/a/align- content/)).
The rule needs specifying for each size of grid, so it might be useful as a SCSS mixin:
@mixin last-grid-row($columns) {
&:nth-child(#{$columns}n+1):nth-last-child(-n+#{$columns}),
&:nth-child(#{$columns}n+1):nth-last-child(-n+#{$columns}) ~ li {
@content;
}
}
Thanks to Mitchel Cabuloy for pointing out that the
sibling selector needs qualifying with the type of sibling (~ li
) to work
properly.