Skip to content

Commit

Permalink
LibWeb: Make offsetTop and offsetLeft behave more like other browsers
Browse files Browse the repository at this point in the history
We now follow the rules from the spec more closely, along with an
unspecified quirk for when the offsetParent is a non-positioned body
element. (Spec bug linked in a comment.)

This fixes a whole bunch of css-flexbox tests on WPT, which already had
correct layout, but the reported metrics from JS API were wrong.
  • Loading branch information
awesomekling committed Jul 25, 2024
1 parent cdfc7a9 commit 7e8737c
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BreakNode <br>
BreakNode <br>
BlockContainer <pre#out> at (8,109) content-size 784x51 children: inline
frag 0 from TextNode start: 0, length: 10, rect: [8,109 72.421875x17] baseline: 13.296875
"well: 0, 0"
frag 1 from TextNode start: 11, length: 13, rect: [8,126 96.765625x17] baseline: 13.296875
"hello: 36, 25"
frag 0 from TextNode start: 0, length: 10, rect: [8,109 72.203125x17] baseline: 13.296875
"well: 8, 8"
frag 1 from TextNode start: 11, length: 13, rect: [8,126 95.359375x17] baseline: 13.296875
"hello: 44, 33"
frag 2 from TextNode start: 25, length: 15, rect: [8,143 113.65625x17] baseline: 13.296875
"friends: 45, 25"
TextNode <#text>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Top: 0
Left: 0
Top: 16
Left: 8
52 changes: 42 additions & 10 deletions Userland/Libraries/LibWeb/HTML/HTMLElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,24 +260,40 @@ int HTMLElement::offset_top() const
if (!layout_node())
return 0;

CSSPixels top_border_edge_of_element;
if (paintable()->is_paintable_box()) {
top_border_edge_of_element = paintable_box()->absolute_border_box_rect().y();
} else {
top_border_edge_of_element = paintable()->box_type_agnostic_position().y();
}

// 2. If the offsetParent of the element is null
// return the y-coordinate of the top border edge of the first CSS layout box associated with the element,
// relative to the initial containing block origin,
// ignoring any transforms that apply to the element and its ancestors, and terminate this algorithm.
auto offset_parent = this->offset_parent();
if (!offset_parent || !offset_parent->layout_node()) {
auto position = paintable()->box_type_agnostic_position();
return position.y().to_int();
return top_border_edge_of_element.to_int();
}

// 3. Return the result of subtracting the y-coordinate of the top padding edge
// of the first box associated with the offsetParent of the element
// from the y-coordinate of the top border edge of the first box associated with the element,
// relative to the initial containing block origin,
// ignoring any transforms that apply to the element and its ancestors.
auto offset_parent_position = offset_parent->paintable()->box_type_agnostic_position();
auto position = paintable()->box_type_agnostic_position();
return position.y().to_int() - offset_parent_position.y().to_int();

// NOTE: We give special treatment to the body element to match other browsers.
// Spec bug: https://github.com/w3c/csswg-drafts/issues/10549

CSSPixels top_padding_edge_of_offset_parent;
if (offset_parent->is_html_body_element() && !offset_parent->paintable()->is_positioned()) {
top_padding_edge_of_offset_parent = 0;
} else if (offset_parent->paintable()->is_paintable_box()) {
top_padding_edge_of_offset_parent = offset_parent->paintable_box()->absolute_padding_box_rect().y();
} else {
top_padding_edge_of_offset_parent = offset_parent->paintable()->box_type_agnostic_position().y();
}
return (top_border_edge_of_element - top_padding_edge_of_offset_parent).to_int();
}

// https://www.w3.org/TR/cssom-view-1/#dom-htmlelement-offsetleft
Expand All @@ -293,24 +309,40 @@ int HTMLElement::offset_left() const
if (!layout_node())
return 0;

CSSPixels left_border_edge_of_element;
if (paintable()->is_paintable_box()) {
left_border_edge_of_element = paintable_box()->absolute_border_box_rect().x();
} else {
left_border_edge_of_element = paintable()->box_type_agnostic_position().x();
}

// 2. If the offsetParent of the element is null
// return the x-coordinate of the left border edge of the first CSS layout box associated with the element,
// relative to the initial containing block origin,
// ignoring any transforms that apply to the element and its ancestors, and terminate this algorithm.
auto offset_parent = this->offset_parent();
if (!offset_parent || !offset_parent->layout_node()) {
auto position = paintable()->box_type_agnostic_position();
return position.x().to_int();
return left_border_edge_of_element.to_int();
}

// 3. Return the result of subtracting the x-coordinate of the left padding edge
// of the first CSS layout box associated with the offsetParent of the element
// from the x-coordinate of the left border edge of the first CSS layout box associated with the element,
// relative to the initial containing block origin,
// ignoring any transforms that apply to the element and its ancestors.
auto offset_parent_position = offset_parent->paintable()->box_type_agnostic_position();
auto position = paintable()->box_type_agnostic_position();
return position.x().to_int() - offset_parent_position.x().to_int();

// NOTE: We give special treatment to the body element to match other browsers.
// Spec bug: https://github.com/w3c/csswg-drafts/issues/10549

CSSPixels left_padding_edge_of_offset_parent;
if (offset_parent->is_html_body_element() && !offset_parent->paintable()->is_positioned()) {
left_padding_edge_of_offset_parent = 0;
} else if (offset_parent->paintable()->is_paintable_box()) {
left_padding_edge_of_offset_parent = offset_parent->paintable_box()->absolute_padding_box_rect().x();
} else {
left_padding_edge_of_offset_parent = offset_parent->paintable()->box_type_agnostic_position().x();
}
return (left_border_edge_of_element - left_padding_edge_of_offset_parent).to_int();
}

// https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetwidth
Expand Down

0 comments on commit 7e8737c

Please sign in to comment.