Guidelines
Description of the bug
css() reads the style attribute of every element in the match set into a single map, merges the new declarations into that one map, then writes the combined string back to all of them.
The result is cross-contamination: if two selected elements start with different inline styles, both end up carrying the union of the two. Setting one property on a set of elements silently rewrites unrelated properties on all of them.
Root cause
src/Helpers/QueryMutators.php:1039-1071 — $css is built once, outside any per-element loop, and attr() then applies the single result to the whole set:
// Get any existing CSS.
$css = [];
foreach ($this->matches as $match) { // <-- accumulates across ALL matches
$style = $match->getAttribute('style');
if (! empty($style)) {
$style_array = explode(';', $style);
foreach ($style_array as $item) {
...
$css[$css_att] = trim($css_val);
}
}
}
...
$this->attr('style', $css_string); // <-- one string, applied to ALL matches
Suggested fix
Move the read-merge-write cycle inside a per-element loop so each element's own style attribute is the basis for its own result.
Workaround
Apply css() to one element at a time when the selected elements do not already share an identical style.
QueryPath version
4.2.0 (also reproduces on main at bed5d2c)
PHP Version and environment (server type, cli provider etc., enclosing libraries and their respective versions)
PHP 8.3.16 CLI (macOS, Homebrew). Not PHP-8 specific — the cause is present on every supported version.
Minimal reproducible PHP+HTML snippet to replicate bug
<?php
require __DIR__ . '/vendor/autoload.php';
$qp = html5qp('<div><p style="color:red"/><p style="font-size:2px"/></div>', 'p');
$qp->css('margin', '0');
var_dump($qp->get(0)->getAttribute('style'));
var_dump($qp->get(1)->getAttribute('style'));
// Both print: 'color: red;font-size: 2px;margin: 0;'
// Expected: 'color: red;margin: 0;' and 'font-size: 2px;margin: 0;'
Guidelines
Description of the bug
css()reads thestyleattribute of every element in the match set into a single map, merges the new declarations into that one map, then writes the combined string back to all of them.The result is cross-contamination: if two selected elements start with different inline styles, both end up carrying the union of the two. Setting one property on a set of elements silently rewrites unrelated properties on all of them.
Root cause
src/Helpers/QueryMutators.php:1039-1071—$cssis built once, outside any per-element loop, andattr()then applies the single result to the whole set:Suggested fix
Move the read-merge-write cycle inside a per-element loop so each element's own
styleattribute is the basis for its own result.Workaround
Apply
css()to one element at a time when the selected elements do not already share an identicalstyle.QueryPath version
4.2.0 (also reproduces on
mainat bed5d2c)PHP Version and environment (server type, cli provider etc., enclosing libraries and their respective versions)
PHP 8.3.16 CLI (macOS, Homebrew). Not PHP-8 specific — the cause is present on every supported version.
Minimal reproducible PHP+HTML snippet to replicate bug