Problem:
selector:not(.hidden):nth-child(even)
selects elements that havent .hidden
class and also are even. But we need to select subset of even elements from the set of elements without .hidden class. Put differently in case of selector:not(.hidden):nth-child(even)
part :nth-child(even)
will ignore :not(.hidden)
part and acts independently, but not select even from visible. By default nth-child
cant ignore hidden rows, cause these rows are still in the DOM.
Solution 1 (works)
Dont hide the rows of the table, but remove them altogether. Save an array of references to DOM elements of table rows (initial state). And on filter action - cycle through this array, and depending on the filtering conditions, call the append
method for the table or remove
for the row
instead of
if (condition) {
row.classList.add('visible')
} else {
row.classList.add('hidden')
}
do
// partically pseudo code
const rows = Array.from(tbody.querySelectorAll<HTMLTableRowElement>('tr'));
onClickOneOf(filterAction, (event) => {
// ...some your stuff
for (const row of rows) {
if (condition) {
tbody.appendChild(row);
} else {
row.remove();
}
}
});
now nth-child
will work correctly
Solution 2 (partially supported yet in some browsers but so cool)
Source: https://developer.chrome.com/articles/css-nth-child-of-s/#zebra-striping-revisited
A classic example where :nth-child()
is used - when creating zebra-striped table. By default, this can be approached as follows:
tr:nth-child(even) {
background-color: lightgrey;
}
This works for static tables, but it becomes problematic when you start to dynamically filter the table contents.
To fix this, we can leverage :nth-child(An+B [of S]?)
by excluding the hidden rows from the An+B logic:
tr:nth-child(even of :not(.hidden-class or other...)) {
background-color: lightgrey;
}