diff --git a/Tests/LibWeb/Layout/expected/grid/abspos-item-aligned-center.txt b/Tests/LibWeb/Layout/expected/grid/abspos-item-aligned-center.txt new file mode 100644 index 0000000000..63b510468b --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/abspos-item-aligned-center.txt @@ -0,0 +1,11 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x220 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x202 children: not-inline + Box at (11,11) content-size 200x200 positioned [GFC] children: not-inline + BlockContainer at (61,61) content-size 100x100 positioned [BFC] children: not-inline + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x222] + PaintableWithLines (BlockContainer) [9,9 782x204] + PaintableBox (Box
.container) [10,10 202x202] + PaintableWithLines (BlockContainer
.box) [60,60 102x102] diff --git a/Tests/LibWeb/Layout/input/grid/abspos-item-aligned-center.html b/Tests/LibWeb/Layout/input/grid/abspos-item-aligned-center.html new file mode 100644 index 0000000000..afc4dd079f --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/abspos-item-aligned-center.html @@ -0,0 +1,19 @@ +
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 8f3532eb8a..9da529b99c 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -1879,6 +1879,95 @@ void GridFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const } } +void GridFormattingContext::layout_absolutely_positioned_element(Box const& box, AvailableSpace const& available_space) +{ + auto& containing_block_state = m_state.get_mutable(*box.containing_block()); + auto& box_state = m_state.get_mutable(box); + auto const& computed_values = box.computed_values(); + + // The border computed values are not changed by the compute_height & width calculations below. + // The spec only adjusts and computes sizes, insets and margins. + box_state.border_left = box.computed_values().border_left().width; + 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; + + compute_width_for_absolutely_positioned_element(box, available_space); + + // NOTE: We compute height before *and* after doing inside layout. + // This is done so that inside layout can resolve percentage heights. + // In some situations, e.g with non-auto top & bottom values, the height can be determined early. + compute_height_for_absolutely_positioned_element(box, available_space, BeforeOrAfterInsideLayout::Before); + + auto independent_formatting_context = layout_inside(box, LayoutMode::Normal, box_state.available_inner_space_or_constraints_from(available_space)); + + compute_height_for_absolutely_positioned_element(box, available_space, BeforeOrAfterInsideLayout::After); + + if (computed_values.inset().left().is_auto() && computed_values.inset().right().is_auto()) { + auto containing_block_width = containing_block_state.content_width(); + auto width_left_for_alignment = containing_block_width - box_state.margin_box_width(); + switch (justification_for_item(box)) { + case CSS::JustifyItems::Normal: + case CSS::JustifyItems::Stretch: + break; + case CSS::JustifyItems::Center: + box_state.inset_left = width_left_for_alignment / 2; + box_state.inset_right = width_left_for_alignment / 2; + break; + case CSS::JustifyItems::Start: + case CSS::JustifyItems::FlexStart: + box_state.inset_right = width_left_for_alignment; + break; + case CSS::JustifyItems::End: + case CSS::JustifyItems::FlexEnd: + box_state.inset_left = width_left_for_alignment; + break; + default: + break; + } + } + + if (computed_values.inset().top().is_auto() && computed_values.inset().bottom().is_auto()) { + auto containing_block_height = containing_block_state.content_height(); + auto height_left_for_alignment = containing_block_height - box_state.margin_box_height(); + switch (alignment_for_item(box)) { + case CSS::AlignItems::Baseline: + // FIXME: Not implemented + case CSS::AlignItems::Stretch: + case CSS::AlignItems::Normal: + break; + case CSS::AlignItems::Start: + case CSS::AlignItems::FlexStart: + case CSS::AlignItems::SelfStart: + box_state.inset_bottom = height_left_for_alignment; + break; + case CSS::AlignItems::End: + case CSS::AlignItems::SelfEnd: + case CSS::AlignItems::FlexEnd: { + box_state.inset_top = height_left_for_alignment; + break; + } + case CSS::AlignItems::Center: + box_state.inset_top = height_left_for_alignment / 2; + box_state.inset_bottom = height_left_for_alignment / 2; + break; + default: + break; + } + } + + CSSPixelPoint used_offset; + used_offset.set_x(box_state.inset_left + box_state.margin_box_left()); + used_offset.set_y(box_state.inset_top + box_state.margin_box_top()); + + // NOTE: Absolutely positioned boxes are relative to the *padding edge* of the containing block. + used_offset.translate_by(-containing_block_state.padding_left, -containing_block_state.padding_top); + box_state.set_content_offset(used_offset); + + if (independent_formatting_context) + independent_formatting_context->parent_context_did_dimension_child_root_box(); +} + void GridFormattingContext::parent_context_did_dimension_child_root_box() { grid_container().for_each_child_of_type([&](Layout::Box& box) { diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h index a277eb6c6d..bf57e4ca03 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h @@ -223,6 +223,7 @@ private: void determine_grid_container_height(); void determine_intrinsic_size_of_grid_container(AvailableSpace const& available_space); + void layout_absolutely_positioned_element(Box const&, AvailableSpace const&); virtual void parent_context_did_dimension_child_root_box() override; void resolve_grid_item_widths();