diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/abspos-with-percentage-padding.txt b/Tests/LibWeb/Layout/expected/block-and-inline/abspos-with-percentage-padding.txt new file mode 100644 index 00000000000..fa5a5f127f7 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/block-and-inline/abspos-with-percentage-padding.txt @@ -0,0 +1,11 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x330 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x312 children: not-inline + BlockContainer at (31,21) content-size 200x200 positioned children: not-inline + BlockContainer at (66,76) content-size 100x100 positioned [BFC] children: not-inline + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x332] + PaintableWithLines (BlockContainer) [9,9 782x314] + PaintableWithLines (BlockContainer
.box) [10,10 272x312] + PaintableWithLines (BlockContainer
.inner) [11,21 210x210] diff --git a/Tests/LibWeb/Layout/expected/grid/abspos-item-with-percentage-padding.txt b/Tests/LibWeb/Layout/expected/grid/abspos-item-with-percentage-padding.txt new file mode 100644 index 00000000000..b1622a14f12 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/abspos-item-with-percentage-padding.txt @@ -0,0 +1,11 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x120 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x102 children: not-inline + Box at (11,11) content-size 200x100 positioned [GFC] children: not-inline + BlockContainer at (122,22) content-size 28x28 positioned [BFC] children: not-inline + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x122] + PaintableWithLines (BlockContainer) [9,9 782x104] + PaintableBox (Box
.grid) [10,10 202x102] + PaintableWithLines (BlockContainer
.abspos-item) [111,11 50x50] diff --git a/Tests/LibWeb/Layout/input/block-and-inline/abspos-with-percentage-padding.html b/Tests/LibWeb/Layout/input/block-and-inline/abspos-with-percentage-padding.html new file mode 100644 index 00000000000..d0c798821c5 --- /dev/null +++ b/Tests/LibWeb/Layout/input/block-and-inline/abspos-with-percentage-padding.html @@ -0,0 +1,22 @@ +
\ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/grid/abspos-item-with-percentage-padding.html b/Tests/LibWeb/Layout/input/grid/abspos-item-with-percentage-padding.html new file mode 100644 index 00000000000..40f720837cf --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/abspos-item-with-percentage-padding.html @@ -0,0 +1,27 @@ +
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index c22f13d69e5..866ccd0ca28 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -216,6 +216,13 @@ bool FlexFormattingContext::is_direction_reverse() const void FlexFormattingContext::populate_specified_margins(FlexItem& item, CSS::FlexDirection flex_direction) const { auto width_of_containing_block = m_flex_container_state.content_width(); + + auto& state = m_state.get_mutable(*item.box); + state.padding_left = item.box->computed_values().padding().left().to_px(item.box, width_of_containing_block); + state.padding_right = item.box->computed_values().padding().right().to_px(item.box, width_of_containing_block); + state.padding_top = item.box->computed_values().padding().top().to_px(item.box, width_of_containing_block); + state.padding_bottom = item.box->computed_values().padding().bottom().to_px(item.box, width_of_containing_block); + // FIXME: This should also take reverse-ness into account if (flex_direction == CSS::FlexDirection::Row || flex_direction == CSS::FlexDirection::RowReverse) { item.borders.main_before = item.box->computed_values().border_left().width; @@ -243,10 +250,10 @@ void FlexFormattingContext::populate_specified_margins(FlexItem& item, CSS::Flex item.borders.cross_before = item.box->computed_values().border_left().width; item.borders.cross_after = item.box->computed_values().border_right().width; - item.padding.main_before = item.box->computed_values().padding().top().to_px(item.box, width_of_containing_block); - item.padding.main_after = item.box->computed_values().padding().bottom().to_px(item.box, width_of_containing_block); - item.padding.cross_before = item.box->computed_values().padding().left().to_px(item.box, width_of_containing_block); - item.padding.cross_after = item.box->computed_values().padding().right().to_px(item.box, width_of_containing_block); + item.padding.main_before = state.padding_top; + item.padding.main_after = state.padding_bottom; + item.padding.cross_before = state.padding_left; + item.padding.cross_after = state.padding_right; item.margins.main_before = item.box->computed_values().margin().top().to_px(item.box, width_of_containing_block); item.margins.main_after = item.box->computed_values().margin().bottom().to_px(item.box, width_of_containing_block); @@ -1604,11 +1611,6 @@ void FlexFormattingContext::copy_dimensions_from_flex_items_to_boxes() for (auto& item : m_flex_items) { auto const& box = item.box; - item.used_values.padding_left = box->computed_values().padding().left().to_px(box, m_flex_container_state.content_width()); - item.used_values.padding_right = box->computed_values().padding().right().to_px(box, m_flex_container_state.content_width()); - item.used_values.padding_top = box->computed_values().padding().top().to_px(box, m_flex_container_state.content_width()); - item.used_values.padding_bottom = box->computed_values().padding().bottom().to_px(box, m_flex_container_state.content_width()); - item.used_values.margin_left = box->computed_values().margin().left().to_px(box, m_flex_container_state.content_width()); item.used_values.margin_right = box->computed_values().margin().right().to_px(box, m_flex_container_state.content_width()); item.used_values.margin_top = box->computed_values().margin().top().to_px(box, m_flex_container_state.content_width()); diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index 4aff93f8e5e..04496eb599f 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -667,13 +667,14 @@ void FormattingContext::compute_width_for_absolutely_positioned_non_replaced_ele auto width_of_containing_block = available_space.width.to_px_or_zero(); auto const& computed_values = box.computed_values(); auto zero_value = CSS::Length::make_px(0); + auto& box_state = m_state.get_mutable(box); auto margin_left = CSS::Length::make_auto(); auto margin_right = CSS::Length::make_auto(); auto const border_left = computed_values.border_left().width; auto const border_right = computed_values.border_right().width; - auto const padding_left = computed_values.padding().left().to_px(box, width_of_containing_block); - auto const padding_right = computed_values.padding().right().to_px(box, width_of_containing_block); + auto const padding_left = box_state.padding_left; + auto const padding_right = box_state.padding_right; auto computed_left = computed_values.inset().left(); auto computed_right = computed_values.inset().right(); @@ -835,14 +836,11 @@ void FormattingContext::compute_width_for_absolutely_positioned_non_replaced_ele } } - auto& box_state = m_state.get_mutable(box); box_state.set_content_width(used_width.to_px(box)); box_state.inset_left = left; box_state.inset_right = right; box_state.margin_left = margin_left.to_px(box); box_state.margin_right = margin_right.to_px(box); - box_state.padding_left = padding_left; - box_state.padding_right = padding_right; } void FormattingContext::compute_width_for_absolutely_positioned_replaced_element(Box const& box, AvailableSpace const& available_space) @@ -962,7 +960,7 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el auto top = box.computed_values().inset().top(); auto bottom = box.computed_values().inset().bottom(); - auto width_of_containing_block = containing_block_width_for(box); + auto width_of_containing_block = available_space.width.to_px_or_zero(); auto height_of_containing_block = available_space.height.to_px_or_zero(); enum class ClampToZero { @@ -970,15 +968,16 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el Yes, }; + auto& state = m_state.get(box); auto try_compute_height = [&](CSS::Length height) -> CSS::Length { auto solve_for = [&](CSS::Length length, ClampToZero clamp_to_zero = ClampToZero::No) { auto unclamped_value = height_of_containing_block - top.to_px(box, height_of_containing_block) - margin_top.to_px(box, width_of_containing_block) - box.computed_values().border_top().width - - box.computed_values().padding().top().to_px(box, width_of_containing_block) + - state.padding_top - apply_min_max_height_constraints(height).to_px(box) - - box.computed_values().padding().bottom().to_px(box, width_of_containing_block) + - state.padding_bottom - box.computed_values().border_bottom().width - margin_bottom.to_px(box, width_of_containing_block) - bottom.to_px(box, height_of_containing_block) @@ -1157,8 +1156,6 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el box_state.inset_bottom = bottom.to_px(box, height_of_containing_block); box_state.margin_top = margin_top.to_px(box, width_of_containing_block); box_state.margin_bottom = margin_bottom.to_px(box, width_of_containing_block); - box_state.padding_top = box.computed_values().padding().top().to_px(box, width_of_containing_block); - box_state.padding_bottom = box.computed_values().padding().bottom().to_px(box, width_of_containing_block); } // NOTE: This is different from content_box_rect_in_ancestor_coordinate_space() as this does *not* follow the containing block chain up, but rather the parent() chain. @@ -1241,6 +1238,12 @@ void FormattingContext::layout_absolutely_positioned_element(Box const& box, Ava box_state.border_top = box.computed_values().border_top().width; box_state.border_bottom = box.computed_values().border_bottom().width; + auto const containing_block_width = available_space.width.to_px_or_zero(); + box_state.padding_left = box.computed_values().padding().left().to_px(box, containing_block_width); + box_state.padding_right = box.computed_values().padding().right().to_px(box, containing_block_width); + box_state.padding_top = box.computed_values().padding().top().to_px(box, containing_block_width); + box_state.padding_bottom = box.computed_values().padding().bottom().to_px(box, containing_block_width); + compute_width_for_absolutely_positioned_element(box, available_space); // NOTE: We compute height before *and* after doing inside layout. @@ -1625,14 +1628,12 @@ CSSPixels FormattingContext::calculate_inner_width(Layout::Box const& box, Avail auto& computed_values = box.computed_values(); if (computed_values.box_sizing() == CSS::BoxSizing::BorderBox) { - auto const padding_left = computed_values.padding().left().resolved(box, width_of_containing_block); - auto const padding_right = computed_values.padding().right().resolved(box, width_of_containing_block); - + auto const& state = m_state.get(box); auto inner_width = width.to_px(box, width_of_containing_block) - computed_values.border_left().width - - padding_left.to_px(box) + - state.padding_left - computed_values.border_right().width - - padding_right.to_px(box); + - state.padding_right; return max(inner_width, 0); } @@ -1645,16 +1646,12 @@ CSSPixels FormattingContext::calculate_inner_height(Layout::Box const& box, Avai auto height_of_containing_block = available_height.to_px_or_zero(); auto& computed_values = box.computed_values(); if (computed_values.box_sizing() == CSS::BoxSizing::BorderBox) { - auto width_of_containing_block = containing_block_width_for(box); - - auto const padding_top = computed_values.padding().top().resolved(box, width_of_containing_block); - auto const padding_bottom = computed_values.padding().bottom().resolved(box, width_of_containing_block); - + auto const& state = m_state.get(box); auto inner_height = height.to_px(box, height_of_containing_block) - computed_values.border_top().width - - padding_top.to_px(box) + - state.padding_top - computed_values.border_bottom().width - - padding_bottom.to_px(box); + - state.padding_bottom; return max(inner_height, 0); } diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 500df930d43..2f30f4be11a 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -1923,6 +1923,10 @@ void GridFormattingContext::layout_absolutely_positioned_element(Box const& box) box_state.border_right = box.computed_values().border_right().width; box_state.border_top = box.computed_values().border_top().width; box_state.border_bottom = box.computed_values().border_bottom().width; + box_state.padding_left = box.computed_values().padding().left().to_px(grid_container(), grid_area_rect.width()); + box_state.padding_right = box.computed_values().padding().right().to_px(grid_container(), grid_area_rect.width()); + box_state.padding_top = box.computed_values().padding().top().to_px(grid_container(), grid_area_rect.width()); + box_state.padding_bottom = box.computed_values().padding().bottom().to_px(grid_container(), grid_area_rect.width()); compute_width_for_absolutely_positioned_element(box, available_space);