diff --git a/Tests/LibWeb/Layout/expected/box-sizing-border-box-for-definite-sizes-without-layout.txt b/Tests/LibWeb/Layout/expected/box-sizing-border-box-for-definite-sizes-without-layout.txt new file mode 100644 index 0000000000..f79242478a --- /dev/null +++ b/Tests/LibWeb/Layout/expected/box-sizing-border-box-for-definite-sizes-without-layout.txt @@ -0,0 +1,11 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x66 children: not-inline + BlockContainer at (8,8) content-size 784x50 children: inline + line 0 width: 89.726562, height: 50, bottom: 50, baseline: 16.914062 + frag 0 from Box start: 0, length: 0, rect: [28,38 49.726562x0] + Box at (28,38) content-size 49.726562x0 flex-container(row) children: not-inline + BlockContainer <(anonymous)> at (28,27.082031) content-size 49.726562x21.835937 flex-item children: inline + line 0 width: 49.726562, height: 21.835937, bottom: 21.835937, baseline: 16.914062 + frag 0 from TextNode start: 0, length: 5, rect: [28,27.082031 49.726562x21.835937] + "Hello" + TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/box-sizing-border-box-for-definite-sizes-without-layout.html b/Tests/LibWeb/Layout/input/box-sizing-border-box-for-definite-sizes-without-layout.html new file mode 100644 index 0000000000..0911ac1b2a --- /dev/null +++ b/Tests/LibWeb/Layout/input/box-sizing-border-box-for-definite-sizes-without-layout.html @@ -0,0 +1,14 @@ +
Hello \ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index db62b6c526..32ef24b418 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -1088,15 +1088,7 @@ void FlexFormattingContext::determine_hypothetical_cross_size_of_item(FlexItem& return; } - auto cross_size = [&]() { - if (item.box->computed_values().box_sizing() == CSS::BoxSizing::BorderBox && !should_treat_cross_size_as_auto(item.box)) { - return max(CSSPixels(0.0f), inner_cross_size(item.box) - item.padding.cross_before - item.padding.cross_after - item.borders.cross_before - item.borders.cross_after); - } - - return inner_cross_size(item.box); - }(); - - item.hypothetical_cross_size = css_clamp(cross_size, clamp_min, clamp_max); + item.hypothetical_cross_size = css_clamp(inner_cross_size(item.box), clamp_min, clamp_max); return; } diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp index d6d77cab55..75342d1572 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp @@ -229,6 +229,29 @@ void LayoutState::UsedValues::set_node(NodeWithStyleAndBoxModelMetrics& node, Us auto const& computed_values = node.computed_values(); + auto adjust_for_box_sizing = [&](CSSPixels unadjusted_pixels, CSS::Size const& computed_size, bool width) -> CSSPixels { + // box-sizing: content-box and/or automatic size don't require any adjustment. + if (computed_values.box_sizing() == CSS::BoxSizing::ContentBox || computed_size.is_auto()) + return unadjusted_pixels; + + // box-sizing: border-box requires us to subtract the relevant border and padding from the size. + CSSPixels border_and_padding; + + if (width) { + border_and_padding = CSSPixels(computed_values.border_left().width) + + computed_values.padding().left().resolved(*m_node, CSS::Length::make_px(containing_block_used_values->content_width())).resolved(*m_node).to_px(*m_node) + + CSSPixels(computed_values.border_right().width) + + computed_values.padding().right().resolved(*m_node, CSS::Length::make_px(containing_block_used_values->content_width())).resolved(*m_node).to_px(*m_node); + } else { + border_and_padding = CSSPixels(computed_values.border_top().width) + + computed_values.padding().top().resolved(*m_node, CSS::Length::make_px(containing_block_used_values->content_width())).resolved(*m_node).to_px(*m_node) + + CSSPixels(computed_values.border_bottom().width) + + computed_values.padding().bottom().resolved(*m_node, CSS::Length::make_px(containing_block_used_values->content_width())).resolved(*m_node).to_px(*m_node); + } + + return unadjusted_pixels - border_and_padding; + }; + auto is_definite_size = [&](CSS::Size const& size, CSSPixels& resolved_definite_size, bool width) { // A size that can be determined without performing layout; that is, // a , @@ -270,22 +293,22 @@ void LayoutState::UsedValues::set_node(NodeWithStyleAndBoxModelMetrics& node, Us auto containing_block_size_as_length = width ? CSS::Length::make_px(containing_block_used_values->content_width()) : CSS::Length::make_px(containing_block_used_values->content_height()); - resolved_definite_size = size.calculated().resolve_length_percentage(node, containing_block_size_as_length).value_or(CSS::Length::make_auto()).to_px(node); + resolved_definite_size = adjust_for_box_sizing(size.calculated().resolve_length_percentage(node, containing_block_size_as_length).value_or(CSS::Length::make_auto()).to_px(node), size, width); return true; } - resolved_definite_size = size.calculated().resolve_length(node)->to_px(node); + resolved_definite_size = adjust_for_box_sizing(size.calculated().resolve_length(node)->to_px(node), size, width); return true; } if (size.is_length()) { VERIFY(!size.is_auto()); // This should have been covered by the Size::is_auto() branch above. - resolved_definite_size = size.length().to_px(node); + resolved_definite_size = adjust_for_box_sizing(size.length().to_px(node), size, width); return true; } if (size.is_percentage()) { if (containing_block_has_definite_size) { auto containing_block_size = width ? containing_block_used_values->content_width() : containing_block_used_values->content_height(); - resolved_definite_size = containing_block_size * size.percentage().as_fraction(); + resolved_definite_size = adjust_for_box_sizing(containing_block_size * size.percentage().as_fraction(), size, width); return true; } return false;