LibWeb: Position abspos items inside grid relative to their grid area

Since grid item's containing block is not grid container but
corresponding grid area, it affect positioning of abspos items.
This commit is contained in:
Aliaksandr Kalenik 2023-10-30 21:52:13 +01:00 committed by Andreas Kling
parent 44001d2178
commit 141f56accc
Notes: sideshowbarker 2024-07-17 03:45:48 +09:00
3 changed files with 91 additions and 2 deletions

View file

@ -0,0 +1,11 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (1,1) content-size 798x120 [BFC] children: not-inline
BlockContainer <body> at (10,10) content-size 780x102 children: not-inline
Box <div.grid> at (11,11) content-size 200x100 positioned [GFC] children: not-inline
BlockContainer <div.abspos-item> at (112,12) content-size 50x50 positioned [BFC] children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x122]
PaintableWithLines (BlockContainer<BODY>) [9,9 782x104]
PaintableBox (Box<DIV>.grid) [10,10 202x102]
PaintableWithLines (BlockContainer<DIV>.abspos-item) [111,11 52x52]

View file

@ -0,0 +1,23 @@
<!DOCTYPE html><style>
* {
border: 1px solid black;
}
.grid {
display: grid;
grid-template-columns: 100px 100px;
grid-template-areas: "a b";
position: relative;
width: 200px;
height: 100px;
}
.abspos-item {
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
grid-area: b;
}
</style><div class="grid"><div class="abspos-item"></div></div>

View file

@ -1958,6 +1958,56 @@ void GridFormattingContext::layout_absolutely_positioned_element(Box const& box,
auto& box_state = m_state.get_mutable(box);
auto const& computed_values = box.computed_values();
auto const& grid_row_start = computed_values.grid_row_start();
auto const& grid_row_end = computed_values.grid_row_end();
auto const& grid_column_start = computed_values.grid_column_start();
auto const& grid_column_end = computed_values.grid_column_end();
int row_start = 0, row_end = 0, column_start = 0, column_end = 0;
if (grid_column_end.has_identifier()) {
if (auto maybe_grid_area = m_grid_areas.get(grid_column_end.identifier()); maybe_grid_area.has_value())
column_end = maybe_grid_area->column_end;
else if (auto line_name_index = get_line_index_by_line_name(grid_column_end.identifier(), grid_container().computed_values().grid_template_columns()); line_name_index > -1)
column_end = line_name_index;
else
column_end = 1;
column_start = column_end - 1;
}
if (grid_column_start.has_identifier()) {
if (auto maybe_grid_area = m_grid_areas.get(grid_column_start.identifier()); maybe_grid_area.has_value())
column_start = maybe_grid_area->column_start;
else if (auto line_name_index = get_line_index_by_line_name(grid_column_start.identifier(), grid_container().computed_values().grid_template_columns()); line_name_index > -1)
column_start = line_name_index;
else
column_start = 0;
}
if (grid_row_end.has_identifier()) {
if (auto maybe_grid_area = m_grid_areas.get(grid_row_end.identifier()); maybe_grid_area.has_value())
row_end = maybe_grid_area->row_end;
else if (auto line_name_index = get_line_index_by_line_name(grid_row_end.identifier(), grid_container().computed_values().grid_template_rows()); line_name_index > -1)
row_end = line_name_index;
else
row_end = 1;
row_start = row_end - 1;
}
if (grid_row_start.has_identifier()) {
if (auto maybe_grid_area = m_grid_areas.get(grid_row_start.identifier()); maybe_grid_area.has_value())
row_start = maybe_grid_area->row_start;
else if (auto line_name_index = get_line_index_by_line_name(grid_row_start.identifier(), grid_container().computed_values().grid_template_rows()); line_name_index > -1)
row_start = line_name_index;
else
row_start = 0;
}
size_t row_span = row_end - row_start;
size_t column_span = column_end - column_start;
GridItem item { box, row_start, row_span, column_start, column_span };
// 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;
@ -2029,9 +2079,14 @@ void GridFormattingContext::layout_absolutely_positioned_element(Box const& box,
}
}
// If an absolutely positioned elements containing block is generated by a grid container,
// the containing block corresponds to the grid area determined by its grid-placement properties.
// The offset properties (top/right/bottom/left) then indicate offsets inwards from the corresponding
// edges of this containing block, as normal.
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());
auto grid_area_offset = get_grid_area_rect(item);
used_offset.set_x(grid_area_offset.x() + box_state.inset_left + box_state.margin_box_left());
used_offset.set_y(grid_area_offset.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);