mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-05-12 14:12:52 +00:00
LibWeb/Layout: Improve grid item sizing for replaced boxes
With this change we no longer stretch "width: auto" for replaced elements and also use "width calculation rules for block-level replaced elements", like suggested by the spec.
This commit is contained in:
parent
2dd657f530
commit
1f8e7c3cca
Notes:
github-actions[bot]
2025-03-20 02:37:49 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: 1f8e7c3cca
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4011
13 changed files with 83 additions and 54 deletions
|
@ -1549,6 +1549,7 @@ void GridFormattingContext::resolve_grid_item_widths()
|
||||||
{
|
{
|
||||||
for (auto& item : m_grid_items) {
|
for (auto& item : m_grid_items) {
|
||||||
CSSPixels containing_block_width = containing_block_size_for_item(item, GridDimension::Column);
|
CSSPixels containing_block_width = containing_block_size_for_item(item, GridDimension::Column);
|
||||||
|
CSS::JustifyItems justification = justification_for_item(item.box);
|
||||||
|
|
||||||
auto const& computed_values = item.box->computed_values();
|
auto const& computed_values = item.box->computed_values();
|
||||||
auto const& computed_width = computed_values.width();
|
auto const& computed_width = computed_values.width();
|
||||||
|
@ -1559,15 +1560,14 @@ void GridFormattingContext::resolve_grid_item_widths()
|
||||||
CSSPixels width;
|
CSSPixels width;
|
||||||
};
|
};
|
||||||
|
|
||||||
ItemAlignment initial {
|
auto try_compute_width = [&item, containing_block_width, justification](CSSPixels a_width, CSS::Size const& computed_width) -> ItemAlignment {
|
||||||
.margin_left = item.used_values.margin_left,
|
auto const& computed_values = item.box->computed_values();
|
||||||
.margin_right = item.used_values.margin_right,
|
|
||||||
.width = item.used_values.content_width()
|
|
||||||
};
|
|
||||||
|
|
||||||
auto try_compute_width = [&](CSSPixels a_width, CSS::Size const& computed_width) -> ItemAlignment {
|
ItemAlignment result = {
|
||||||
ItemAlignment result = initial;
|
.margin_left = item.used_values.margin_left,
|
||||||
result.width = a_width;
|
.margin_right = item.used_values.margin_right,
|
||||||
|
.width = a_width
|
||||||
|
};
|
||||||
|
|
||||||
// Auto margins absorb positive free space prior to alignment via the box alignment properties.
|
// Auto margins absorb positive free space prior to alignment via the box alignment properties.
|
||||||
auto free_space_left_for_margins = containing_block_width - result.width - item.used_values.border_left - item.used_values.border_right - item.used_values.padding_left - item.used_values.padding_right - item.used_values.margin_left - item.used_values.margin_right;
|
auto free_space_left_for_margins = containing_block_width - result.width - item.used_values.border_left - item.used_values.border_right - item.used_values.padding_left - item.used_values.padding_right - item.used_values.margin_left - item.used_values.margin_right;
|
||||||
|
@ -1578,13 +1578,14 @@ void GridFormattingContext::resolve_grid_item_widths()
|
||||||
result.margin_left = free_space_left_for_margins;
|
result.margin_left = free_space_left_for_margins;
|
||||||
} else if (computed_values.margin().right().is_auto()) {
|
} else if (computed_values.margin().right().is_auto()) {
|
||||||
result.margin_right = free_space_left_for_margins;
|
result.margin_right = free_space_left_for_margins;
|
||||||
} else if (computed_width.is_auto()) {
|
} else if (computed_width.is_auto() && !item.box->is_replaced_box()) {
|
||||||
result.width += free_space_left_for_margins;
|
result.width += free_space_left_for_margins;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto free_space_left_for_alignment = containing_block_width - a_width - item.used_values.border_left - item.used_values.border_right - item.used_values.padding_left - item.used_values.padding_right - item.used_values.margin_left - item.used_values.margin_right;
|
auto free_space_left_for_alignment = containing_block_width - a_width - item.used_values.border_left - item.used_values.border_right - item.used_values.padding_left - item.used_values.padding_right - item.used_values.margin_left - item.used_values.margin_right;
|
||||||
switch (justification_for_item(item.box)) {
|
switch (justification) {
|
||||||
case CSS::JustifyItems::Normal:
|
case CSS::JustifyItems::Normal:
|
||||||
|
break;
|
||||||
case CSS::JustifyItems::Stretch:
|
case CSS::JustifyItems::Stretch:
|
||||||
break;
|
break;
|
||||||
case CSS::JustifyItems::Center:
|
case CSS::JustifyItems::Center:
|
||||||
|
@ -1613,13 +1614,18 @@ void GridFormattingContext::resolve_grid_item_widths()
|
||||||
|
|
||||||
ItemAlignment used_alignment;
|
ItemAlignment used_alignment;
|
||||||
AvailableSpace available_space { AvailableSize::make_definite(containing_block_width), AvailableSize::make_indefinite() };
|
AvailableSpace available_space { AvailableSize::make_definite(containing_block_width), AvailableSize::make_indefinite() };
|
||||||
if (computed_width.is_auto()) {
|
if (item.box->is_replaced_box() && item.box->has_natural_width()) {
|
||||||
used_alignment = try_compute_width(calculate_fit_content_width(item.box, available_space), computed_width);
|
auto width = tentative_width_for_replaced_element(item.box, computed_values.width(), available_space);
|
||||||
} else if (computed_width.is_fit_content()) {
|
used_alignment = try_compute_width(width, computed_width);
|
||||||
used_alignment = try_compute_width(calculate_fit_content_width(item.box, available_space), computed_width);
|
|
||||||
} else {
|
} else {
|
||||||
auto width_px = calculate_inner_width(item.box, available_space.width, computed_width);
|
if (computed_width.is_auto() || computed_width.is_fit_content()) {
|
||||||
used_alignment = try_compute_width(width_px, computed_width);
|
auto fit_content_width = calculate_fit_content_width(item.box, available_space);
|
||||||
|
used_alignment = try_compute_width(fit_content_width, computed_width);
|
||||||
|
used_alignment = try_compute_width(calculate_fit_content_width(item.box, available_space), computed_width);
|
||||||
|
} else {
|
||||||
|
auto width_px = calculate_inner_width(item.box, available_space.width, computed_width);
|
||||||
|
used_alignment = try_compute_width(width_px, computed_width);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!should_treat_max_width_as_none(item.box, m_available_space->width)) {
|
if (!should_treat_max_width_as_none(item.box, m_available_space->width)) {
|
||||||
|
@ -1648,6 +1654,7 @@ void GridFormattingContext::resolve_grid_item_heights()
|
||||||
{
|
{
|
||||||
for (auto& item : m_grid_items) {
|
for (auto& item : m_grid_items) {
|
||||||
CSSPixels containing_block_height = containing_block_size_for_item(item, GridDimension::Row);
|
CSSPixels containing_block_height = containing_block_size_for_item(item, GridDimension::Row);
|
||||||
|
CSS::AlignItems alignment = alignment_for_item(item.box);
|
||||||
|
|
||||||
auto const& computed_values = item.box->computed_values();
|
auto const& computed_values = item.box->computed_values();
|
||||||
auto const& computed_height = computed_values.height();
|
auto const& computed_height = computed_values.height();
|
||||||
|
@ -1658,15 +1665,14 @@ void GridFormattingContext::resolve_grid_item_heights()
|
||||||
CSSPixels height;
|
CSSPixels height;
|
||||||
};
|
};
|
||||||
|
|
||||||
ItemAlignment initial {
|
auto try_compute_height = [&item, containing_block_height, alignment](CSSPixels a_height) -> ItemAlignment {
|
||||||
.margin_top = item.used_values.margin_top,
|
auto const& computed_values = item.box->computed_values();
|
||||||
.margin_bottom = item.used_values.margin_bottom,
|
|
||||||
.height = item.used_values.content_height()
|
|
||||||
};
|
|
||||||
|
|
||||||
auto try_compute_height = [&](CSSPixels a_height) -> ItemAlignment {
|
ItemAlignment result = {
|
||||||
ItemAlignment result = initial;
|
.margin_top = item.used_values.margin_top,
|
||||||
result.height = a_height;
|
.margin_bottom = item.used_values.margin_bottom,
|
||||||
|
.height = a_height
|
||||||
|
};
|
||||||
|
|
||||||
CSSPixels height = a_height;
|
CSSPixels height = a_height;
|
||||||
auto underflow_px = containing_block_height - height - item.used_values.border_top - item.used_values.border_bottom - item.used_values.padding_top - item.used_values.padding_bottom - item.used_values.margin_top - item.used_values.margin_bottom;
|
auto underflow_px = containing_block_height - height - item.used_values.border_top - item.used_values.border_bottom - item.used_values.padding_top - item.used_values.padding_bottom - item.used_values.margin_top - item.used_values.margin_bottom;
|
||||||
|
@ -1678,13 +1684,14 @@ void GridFormattingContext::resolve_grid_item_heights()
|
||||||
result.margin_top = underflow_px;
|
result.margin_top = underflow_px;
|
||||||
} else if (computed_values.margin().bottom().is_auto()) {
|
} else if (computed_values.margin().bottom().is_auto()) {
|
||||||
result.margin_bottom = underflow_px;
|
result.margin_bottom = underflow_px;
|
||||||
} else if (computed_values.height().is_auto()) {
|
} else if (computed_values.height().is_auto() && !item.box->is_replaced_box()) {
|
||||||
height += underflow_px;
|
height += underflow_px;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (alignment_for_item(item.box)) {
|
switch (alignment) {
|
||||||
case CSS::AlignItems::Baseline:
|
case CSS::AlignItems::Baseline:
|
||||||
// FIXME: Not implemented
|
// FIXME: Not implemented
|
||||||
|
break;
|
||||||
case CSS::AlignItems::Stretch:
|
case CSS::AlignItems::Stretch:
|
||||||
case CSS::AlignItems::Normal:
|
case CSS::AlignItems::Normal:
|
||||||
result.height = height;
|
result.height = height;
|
||||||
|
|
11
Tests/LibWeb/Layout/expected/grid/replaced-item-2.txt
Normal file
11
Tests/LibWeb/Layout/expected/grid/replaced-item-2.txt
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (0,0) content-size 800x116 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (8,8) content-size 100x100 children: not-inline
|
||||||
|
Box <div.img-wrapper> at (8,8) content-size 100x100 [GFC] children: not-inline
|
||||||
|
ImageBox <img> at (8,8) content-size 10x10 children: not-inline
|
||||||
|
|
||||||
|
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||||
|
PaintableWithLines (BlockContainer<HTML>) [0,0 800x116]
|
||||||
|
PaintableWithLines (BlockContainer<BODY>) [8,8 100x100]
|
||||||
|
PaintableBox (Box<DIV>.img-wrapper) [8,8 100x100]
|
||||||
|
ImagePaintable (ImageBox<IMG>) [8,8 10x10]
|
12
Tests/LibWeb/Layout/input/grid/replaced-item-2.html
Normal file
12
Tests/LibWeb/Layout/input/grid/replaced-item-2.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html><style>
|
||||||
|
body {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
.img-wrapper {
|
||||||
|
display: grid;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: darkorchid;
|
||||||
|
}
|
||||||
|
</style><div class="img-wrapper"><img src="data:image/webp;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAADUlEQVR4nGNgGAWkAwABNgABVtF/yAAAAABJRU5ErkJggg=="></div>
|
|
@ -2,6 +2,7 @@ Harness status: OK
|
||||||
|
|
||||||
Found 2 tests
|
Found 2 tests
|
||||||
|
|
||||||
2 Fail
|
1 Pass
|
||||||
|
1 Fail
|
||||||
Fail .before 1
|
Fail .before 1
|
||||||
Fail .after 2
|
Pass .after 2
|
|
@ -2,6 +2,7 @@ Harness status: OK
|
||||||
|
|
||||||
Found 2 tests
|
Found 2 tests
|
||||||
|
|
||||||
2 Fail
|
1 Pass
|
||||||
Fail .before 1
|
1 Fail
|
||||||
|
Pass .before 1
|
||||||
Fail .after 2
|
Fail .after 2
|
|
@ -2,7 +2,6 @@ Harness status: OK
|
||||||
|
|
||||||
Found 2 tests
|
Found 2 tests
|
||||||
|
|
||||||
1 Pass
|
2 Pass
|
||||||
1 Fail
|
|
||||||
Pass .before 1
|
Pass .before 1
|
||||||
Fail .after 2
|
Pass .after 2
|
|
@ -2,7 +2,6 @@ Harness status: OK
|
||||||
|
|
||||||
Found 2 tests
|
Found 2 tests
|
||||||
|
|
||||||
1 Pass
|
2 Pass
|
||||||
1 Fail
|
Pass .before 1
|
||||||
Fail .before 1
|
|
||||||
Pass .after 2
|
Pass .after 2
|
|
@ -2,6 +2,7 @@ Harness status: OK
|
||||||
|
|
||||||
Found 2 tests
|
Found 2 tests
|
||||||
|
|
||||||
2 Fail
|
1 Pass
|
||||||
|
1 Fail
|
||||||
Fail .before 1
|
Fail .before 1
|
||||||
Fail .after 2
|
Pass .after 2
|
|
@ -4,5 +4,5 @@ Found 2 tests
|
||||||
|
|
||||||
1 Pass
|
1 Pass
|
||||||
1 Fail
|
1 Fail
|
||||||
Fail .before 1
|
Pass .before 1
|
||||||
Pass .after 2
|
Fail .after 2
|
|
@ -2,7 +2,6 @@ Harness status: OK
|
||||||
|
|
||||||
Found 2 tests
|
Found 2 tests
|
||||||
|
|
||||||
1 Pass
|
2 Pass
|
||||||
1 Fail
|
|
||||||
Pass .before 1
|
Pass .before 1
|
||||||
Fail .after 2
|
Pass .after 2
|
|
@ -2,7 +2,6 @@ Harness status: OK
|
||||||
|
|
||||||
Found 2 tests
|
Found 2 tests
|
||||||
|
|
||||||
1 Pass
|
2 Pass
|
||||||
1 Fail
|
Pass .before 1
|
||||||
Fail .before 1
|
|
||||||
Pass .after 2
|
Pass .after 2
|
|
@ -2,11 +2,11 @@ Harness status: OK
|
||||||
|
|
||||||
Found 6 tests
|
Found 6 tests
|
||||||
|
|
||||||
1 Pass
|
3 Pass
|
||||||
5 Fail
|
3 Fail
|
||||||
Fail .before 1
|
Fail .before 1
|
||||||
Fail .before 2
|
Pass .before 2
|
||||||
Fail .before 3
|
Fail .before 3
|
||||||
Fail .after 4
|
Fail .after 4
|
||||||
Pass .after 5
|
Pass .after 5
|
||||||
Fail .after 6
|
Pass .after 6
|
|
@ -2,11 +2,11 @@ Harness status: OK
|
||||||
|
|
||||||
Found 6 tests
|
Found 6 tests
|
||||||
|
|
||||||
1 Pass
|
3 Pass
|
||||||
5 Fail
|
3 Fail
|
||||||
Fail .before 1
|
Fail .before 1
|
||||||
Pass .before 2
|
Pass .before 2
|
||||||
Fail .before 3
|
Pass .before 3
|
||||||
Fail .after 4
|
Fail .after 4
|
||||||
Fail .after 5
|
Pass .after 5
|
||||||
Fail .after 6
|
Fail .after 6
|
Loading…
Add table
Add a link
Reference in a new issue