From 52158e83ae01d356cc614db236817b7825bae8b3 Mon Sep 17 00:00:00 2001 From: Pierre Le Fevre Date: Wed, 4 Mar 2026 21:07:37 +0100 Subject: [PATCH] Fix em resolution and add missing position offset properties - Fix em unit resolution for non-font-size properties: em now resolves relative to the element's own computed font-size (per CSS spec) instead of the parent's font-size. Font-size itself already correctly uses parent font-size for em resolution in its own handler. - Add missing 'right' and 'left' position offset property handling in apply_property (only 'top' and 'bottom' were handled). - Update em_margin_relative_to_font_size test to assert correct value (2em * 20px = 40px, not 2em * 16px = 32px). Co-Authored-By: Claude Opus 4.6 --- crates/style/src/computed.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/style/src/computed.rs b/crates/style/src/computed.rs index 7c8f86e..494be34 100644 --- a/crates/style/src/computed.rs +++ b/crates/style/src/computed.rs @@ -389,9 +389,11 @@ u { // Resolve a CssValue to f32 px given context // --------------------------------------------------------------------------- -fn resolve_length(value: &CssValue, parent_font_size: f32, current_font_size: f32) -> Option { +fn resolve_length(value: &CssValue, _parent_font_size: f32, current_font_size: f32) -> Option { match value { - CssValue::Length(n, unit) => Some(resolve_length_unit(*n, *unit, parent_font_size)), + // Em units resolve relative to the element's own computed font-size + // (for properties other than font-size, which has its own handling). + CssValue::Length(n, unit) => Some(resolve_length_unit(*n, *unit, current_font_size)), CssValue::Percentage(p) => Some((*p / 100.0) as f32 * current_font_size), CssValue::Zero => Some(0.0), CssValue::Number(n) if *n == 0.0 => Some(0.0), @@ -734,7 +736,9 @@ fn apply_property( // Position offsets "top" => style.top = resolve_length_or_auto(value, parent_fs, current_fs), + "right" => style.right = resolve_length_or_auto(value, parent_fs, current_fs), "bottom" => style.bottom = resolve_length_or_auto(value, parent_fs, current_fs), + "left" => style.left = resolve_length_or_auto(value, parent_fs, current_fs), // Overflow "overflow" => { @@ -1498,9 +1502,8 @@ mod tests { let div_node = &body_node.children[0]; assert_eq!(div_node.style.font_size, 20.0); - // margin-top em resolves relative to parent font-size (16px body) - // because margin is not font-size itself - assert_eq!(div_node.style.margin_top, LengthOrAuto::Length(32.0)); + // margin-top 2em resolves relative to the element's own computed font-size (20px) + assert_eq!(div_node.style.margin_top, LengthOrAuto::Length(40.0)); } #[test] -- 2.51.2