I have a list of 20+ items. The background-color changes using the :nth-child(2n+1) selector. (ie. even item black, odd item white). When I click a button to filter out specific items using the jQuery Isotope plugin it adds a .isotope-hidden class to the items I want to filter out, which changes the position of the list item to 0,0 and opacity to 0.
When this happens the remaining items are left with the original black/white background-colors, which are now no longer in order.
Does anyone know a way to "repaint' the css using the :nth-child(2n+1) selector on the items that do not contain the .isotope-hidden class.
I tried
#element tr:not(.isotope-hidden):nth-child(2n+1)
with no avail.
Any help would be appreciated. Thank you.
Nth-child can be counterintuitive when working with a filtered selection of a group.
Use .each() to get around its limitations:
var count = 1;
$('#element tr:not(.isotope-hidden)').each(function(){
if ( count++ % 2 == 1 ) $(this).css('background-color','white')
})
CSS selectors — in particular, pseudo-classes, and in particular :not()
and the :nth-*()
family of pseudo-classes — do not work as "filters"; there's a bit of an explanation here, although it seems a little awkward in retrospect. Here's a better explanation.
Simple selectors in a sequence aren't processed in the order they are written one by one; rather, they are a set of conditions that an element must match in order for styles to apply to it, and the element must match all these conditions as they are, together. Or instead of calling them conditions you could also call them descriptors, but I would consider "filters" a misnomer when it comes to CSS selectors.
Your selector means:
Select this element if and only if it is located within #element
and it matches all these conditions:
- It is a
tr
element
- It does not have the class
isotope-hidden
- It is the (2n+1)th child of its parent
It does not mean:
- Look inside the contents of
#element
- Select all
tr
elements
- Filter out elements that do not have the class
isotope-hidden
among these elements
- Apply styles to every (2n+1)th child among these filtered elements
Even if you could "repaint" or reapply styles after filtering them out, it wouldn't work anyway. This is because whether or not an element the isotope-hidden
class (or even whether or not it's a tr
!), the :not(.isotope-hidden)
selector isn't going to change the fact that an element that is :nth-child(1)
is the first child of its parent in the DOM, an element that is :nth-child(2)
is the second child of its parent in the DOM, and so on.
If you need sequential filters, you won't be able to do this with a pure CSS selector; you'll have to use jQuery's filter methods, which were designed for this very purpose, to add a class to the respective elements which you can then use to apply your styles:
$('#element tr').not('.isotope-hidden').filter(':even');
As an aside, this can also be rewritten as a single jQuery selector, using its filter selectors:
$('#element tr:not(.isotope-hidden):even');
However, despite the similar syntax, there is a vast difference between true CSS selectors and jQuery filters, which is outlined in this answer.