You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A selector with two nth-child() pseudo-classes is cut down to the first #522
Part of #520 (step 2). Upstream: mpdf#83 (closed, but it still reproduces).
CssParser::processCssSelector() takes the spaces out of an nth-child() formula by replacing a greedy NTH-CHILD\(.*\) with the first formula it found (src/Css/CssParser.php:253-255). The greedy match runs from the first nth-child( to the last ) in the selector, so everything in between is deleted. This happens before the selector is split, so #521 cannot see it.
Measured on gravitypdf at b6a07921, PHP 8.5.4. A table of 3 rows and 2 columns:
4 cells: every cell of rows 1 and 3, as tr:nth-child(odd)
Any ) later in the selector does the same. tr:nth-child(2) td:not(.x) becomes tr:nth-child(2) and colours the whole row.
Fix. Normalise each NTH-CHILD(…) on its own with preg_replace_callback(), taking the spaces out of each formula. Tried: the rule above then fills 2 cells, and td:nth-child(2n + 1) still works.
Tests. The two selectors above, asserting backgrounds rather than colours (a row's color never reaches its cells), and a single nth-child() with spaces in its formula.
#519 fixed both cases listed here: tr:nth-child(odd) td:nth-child(2) shades 2 cells, and tr:nth-child(2) td:not(.x) is dropped whole. One form was left. When something follows the argument inside the same part, as in td:nth-child(2):not(.x), td:nth-child(2):nth-child(odd) or td:nth-child(2 of .x), the rule was still applied as td:nth-child(2). #564 fixes that and adds a test for tr:nth-child(2) td:not(.x).
Activity
jakejackson1 commentedon Sep 29, 2026
#519 fixed both cases listed here:
tr:nth-child(odd) td:nth-child(2)shades 2 cells, andtr:nth-child(2) td:not(.x)is dropped whole. One form was left. When something follows the argument inside the same part, as intd:nth-child(2):not(.x),td:nth-child(2):nth-child(odd)ortd:nth-child(2 of .x), the rule was still applied astd:nth-child(2). #564 fixes that and adds a test fortr:nth-child(2) td:not(.x).