LibWeb: Recompute relative units in Element::recompute_inherited_style()

Properties with relative units has to be recomputed in inherited style
update as they depend on the parent's style.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/3364
This commit is contained in:
Aliaksandr Kalenik 2025-01-26 21:49:17 +01:00 committed by Andreas Kling
commit cfe9b7a82b
Notes: github-actions[bot] 2025-01-26 22:11:49 +00:00
3 changed files with 58 additions and 2 deletions

View file

@ -20,6 +20,7 @@
#include <LibWeb/CSS/SelectorEngine.h>
#include <LibWeb/CSS/StyleComputer.h>
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
#include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
#include <LibWeb/DOM/Attr.h>
#include <LibWeb/DOM/DOMTokenList.h>
@ -567,15 +568,21 @@ CSS::RequiredInvalidationAfterStyleChange Element::recompute_style()
CSS::RequiredInvalidationAfterStyleChange Element::recompute_inherited_style()
{
// Traversal of the subtree is necessary to update the animated properties inherited from the target element.
auto computed_properties = this->computed_properties();
if (!computed_properties || !layout_node())
if (!m_cascaded_properties || !computed_properties || !layout_node())
return {};
CSS::RequiredInvalidationAfterStyleChange invalidation;
for (auto i = to_underlying(CSS::first_property_id); i <= to_underlying(CSS::last_property_id); ++i) {
auto property_id = static_cast<CSS::PropertyID>(i);
auto const& preabsolutized_value = m_cascaded_properties->property(property_id);
// Update property if it uses relative units as it might have been affected by a change in ancestor element style.
if (preabsolutized_value && preabsolutized_value->is_length() && preabsolutized_value->as_length().length().is_font_relative()) {
auto is_inherited = computed_properties->is_property_inherited(property_id);
computed_properties->set_property(property_id, *preabsolutized_value, is_inherited ? CSS::ComputedProperties::Inherited::Yes : CSS::ComputedProperties::Inherited::No);
invalidation |= CSS::compute_property_invalidation(property_id, preabsolutized_value, preabsolutized_value);
}
if (!computed_properties->is_property_inherited(property_id))
continue;
RefPtr old_value = computed_properties->maybe_null_property(property_id);

View file

@ -0,0 +1,6 @@
(before) child.style.width: 192px
(before) child.style.height: 192px
(before) child.style.fontSize: 96px
(after) child.style.width: 600px
(after) child.style.height: 600px
(after) child.style.fontSize: 300px

View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<head>
<script src="include.js"></script>
<style>
.parent {
font-size: 32px;
}
.child {
font-size: 3em;
width: 2em;
height: 2em;
color: blue;
background-color: magenta;
}
</style>
</head>
<body>
<div class="parent" id="parentElement">
<p class="child">
Hello!
</p>
</div>
<script>
function increaseParentSize() {
document.getElementById('parentElement').style.fontSize = '100px';
}
test(() => {
const childStyleBefore = window.getComputedStyle(document.querySelector('.child'));
println("(before) child.style.width: " + childStyleBefore.width);
println("(before) child.style.height: " + childStyleBefore.height);
println("(before) child.style.fontSize: " + childStyleBefore.fontSize);
increaseParentSize();
const childStyleAfter = window.getComputedStyle(document.querySelector('.child'));
println("(after) child.style.width: " + childStyleAfter.width);
println("(after) child.style.height: " + childStyleAfter.height);
println("(after) child.style.fontSize: " + childStyleAfter.fontSize);
});
</script>
</body>
</html>