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 descendant rule with a part mPDF cannot match is applied to the element its first parts name #521
SelectorParser::parseCascadedSelector() stops at the first part of a descendant selector it cannot parse and returns the parts before it (if (!$tag) { break; }, src/Css/SelectorParser.php:152). CssParser::processCssSelector() stores what is left with the depth of the whole selector (src/Css/CssParser.php:291). The shortened rule then passes the depth check in CssMerger::setMergedCss() and is applied to the element its first parts name. On the table path setMergedCss() does not check depth at all.
Measured on gravitypdf at b6a07921, PHP 8.5.4.
Rule
Treated as
Effect
div p > span {color:red} on <div><p>
div p
the p is red
div p a:hover {color:red} on <div><p>
div p
the p text is red
nav ul li:last-child {color:red}
nav ul
the ul is red, so every li inherits it
table td > span {color:red} on <table><tr><td>
table td
the cell is red
.a p {color:green} .a p > span {color:red} on <div class="a"><p>
.a p
red: the shortened rule is stored in the same node as the real one and overrides it
Framework and CMS stylesheets contain rules of exactly this shape. When only one part is left nothing visible happens (checked with .a > .b), because the properties land where no lookup reads them.
Fix.parseCascadedSelector() returns no levels when any part fails, as parseSimpleSelector() already does, so the rule is dropped as a browser drops what it cannot match. A fix is committed locally as e88dd209 on fix/selector-truncation, based on 973ef247. It merges cleanly onto b6a07921 and makes every row above match a browser. Rebase it and name the branch after this issue.
No upstream issue found. The closest, mpdf#138, renders identically before and after.
Tests. The five rows above, plus div p and .a .b p still applying.
Activity
jakejackson1 commentedon Sep 28, 2026
Completed by #519 (merged as
d660a410).