When table rows use the HTML hidden attribute, plain tr:nth-child(even) still counts them while deciding which rows are even. Filter the sibling list inside :nth-child() to keep the visible rows striped in sequence:
tr:nth-child(even of :not([hidden])) {
background: #eee;
}
The of clause makes the position calculation use only rows that do not have hidden. The selector’s support can vary in some browsers, so check it against your project’s target browsers if older versions matter (MDN Web Docs).
As an Amazon Associate I earn from qualifying purchases.
Why do hidden rows shift the zebra stripes?
:nth-child() calculates a child’s position among its element siblings, starting at 1. It does not automatically count only siblings of the same element type. In tr:nth-child(even), the selected element must be a tr, but its position is calculated from the full sibling list. even means positions 2, 4, 6, and so on (MDN Web Docs).
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
A row with hidden remains in the document and in that sibling list. It can therefore change the position of the rows after it, even though it is not displayed. The result can look like the stripes have merged or restarted unexpectedly.
#1 Best Overall
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
What does the of clause change?
In tr:nth-child(even of :not([hidden])), the selector after of first defines which siblings take part in the index: only those that do not have the hidden attribute. The pseudo-class then selects the even positions within that filtered set. This is the form specified for robust zebra striping when rows are hidden with the HTML attribute (W3C Selectors Level 4).
Three selectors, three outcomes
tr:nth-child(even)indexes all child elements, then matches even-position children that are rows.tr:not([hidden]):nth-child(even)also indexes all child elements first. It adds a condition that the matched row must not havehidden, but does not remove hidden siblings from the position calculation.tr:nth-child(even of :not([hidden]))filters the sibling set before calculating even positions, which preserves alternating stripes among the included rows.
Will this work for every kind of hidden row?
No. The filter matches rows based on the hidden attribute. If your code removes a row from the DOM, it is no longer a sibling and cannot affect the count. But a row that is merely made transparent or concealed by another CSS or application state still matches :not([hidden]). For those cases, change the filter to match the actual state or use the hidden attribute consistently.
Rank #2
What about browser support?
The of syntax is documented by MDN as widely available, with a qualification that some parts may vary in support. If you must support older browsers, verify the exact syntax in the browsers your project targets before relying on it (MDN Web Docs).
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesQuick Recap
Best Value
Rank #4
Rank #3
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




