I have an unordered list, which can contain either an even or odd number of items. I'm looking for a CSS-only way to remove the border from the last 2 li
tags if the number of li
s is even. The :last-child
pseudo-selector removes the last one regardless.
li { float: left; border-bottom: 1px solid #000; } li:last-child{ border-bottom: none; }
li
s+============================================+ + 1 | 2 + +--------------------------------------------+ + 3 | + +============================================+
+============================================+ + 1 | 2 + +--------------------------------------------+ + 3 | 4 + +--------------------- + +============================================+
So I figured I could use li:nth-last-child()
but I can't figure out what should be the equation to grab the last odd child.
It's not 2n+1
, 2n-1
, n-1
, or anything I can think of. Please help.
The :nth-last-child(n) selector matches every element that is the nth child, regardless of type, of its parent, counting from the last child. n can be a number, a keyword, or a formula.
But here is the correct explanation of the math: f(n) = -n+3 f(0) = -0+3 = 3 <- 3rd row from the bottom f(1) = -1+3 = 2 <- 2nd row from the bottom f(2) = -2+3 = 1 <- 1st row from the bottom f(3) = -3+3 = 0 <- nothing f(3) = -4+3 = -1 <- nothing etc...
The :last-child selector allows you to target the last element directly inside its containing element. It is defined in the CSS Selectors Level 3 spec as a “structural pseudo-class”, meaning it is used to style content based on its relationship with parent and sibling content.
nth-last-child counts backwards from the last child, so to grab the second to last, the expression is:
li:nth-last-child(2)
You can combine pseudo-selectors, so to select the 2nd to last child, but only when it's odd, use:
li:nth-last-child(2):nth-child(odd) {border-bottom: none;}
And so, the whole thing should be:
li:last-child, li:nth-last-child(2):nth-child(odd) {border-bottom: none;}
In answer to @ithil's question, here's how I'd write it in SASS:
li &:last-child, &:nth-last-child(2):nth-child(odd) border-bottom: none
It's not that much simpler, since the selection of the 'second-to-last odd child' is always going to require the 'two step' selector.
In answer to @Caspert's question, you can do this for arbitrarily many last elements by grouping more selectors (there feels like there should be some xn+y
pattern to do this without grouping, but AFAIU these patterns just work by counting backwards from the last element).
For three last elements:
li:last-child, li:nth-last-child(2):nth-child(odd), li:nth-last-child(3):nth-child(odd) {border-bottom: none;}
This is a place where something like SASS can help, to generate the selectors for you. I would structure this as a placeholder class, and extend the element with it, and set the number of columns in a variable like this:
$number-of-columns: 3 %no-border-on-last-row @for $i from 1 through $number-of-columns &:nth-last-child($i):nth-child(odd) border-bottom: none //Then, to use it in your layout, just extend: .column-grid-list li @extend %no-border-on-last-row
Another alternative:
li:last-child:not(:nth-child(odd))
Here is a fiddle: http://jsfiddle.net/W72nR/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With