1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 18:07:34 +00:00

LibWeb: Honor column-gap and row-gap CSS properties in flex layout

This isn't actually part of CSS-FLEXBOX-1, but all major engines honor
these properties in flex layout, and it's widely used on the web.

There's a bug open against the flexbox spec where fantasai says the
algorithm will be updated in CSS-FLEXBOX-2:
https://github.com/w3c/csswg-drafts/issues/2336

I've added comments to all the places where we adjust calculations for
gaps with "CSS-FLEXBOX-2" so we can find them easily. When that spec
becomes available, we can add proper spec links.
This commit is contained in:
Andreas Kling 2023-04-14 10:35:26 +02:00
parent 7dd3c4a79c
commit 47c21cc349
4 changed files with 66 additions and 1 deletions

View file

@ -852,6 +852,8 @@ void FlexFormattingContext::collect_flex_items_into_flex_lines()
}
line.items.append(item);
line_main_size += outer_hypothetical_main_size;
// CSS-FLEXBOX-2: Account for gap between flex items.
line_main_size += main_gap();
}
m_flex_lines.append(move(line));
}
@ -873,6 +875,8 @@ void FlexFormattingContext::resolve_flexible_lengths_for_line(FlexLine& line)
for (auto const& item : line.items) {
sum += item.outer_hypothetical_main_size();
}
// CSS-FLEXBOX-2: Account for gap between flex items.
sum += main_gap() * (line.items.size() - 1);
if (sum < inner_main_size(flex_container()))
return FlexFactor::FlexGrowFactor;
return FlexFactor::FlexShrinkFactor;
@ -917,6 +921,8 @@ void FlexFormattingContext::resolve_flexible_lengths_for_line(FlexLine& line)
else
sum += item.outer_flex_base_size();
}
// CSS-FLEXBOX-2: Account for gap between flex items.
sum += main_gap() * (line.items.size() - 1);
return inner_main_size(flex_container()) - sum;
};
auto const initial_free_space = calculate_remaining_free_space();
@ -1224,6 +1230,9 @@ void FlexFormattingContext::distribute_any_remaining_free_space()
+ item.padding.main_before + item.padding.main_after;
}
// CSS-FLEXBOX-2: Account for gap between flex items.
used_main_space += main_gap() * (flex_line.items.size() - 1);
if (flex_line.remaining_free_space > 0) {
CSSPixels size_per_auto_margin = flex_line.remaining_free_space / (float)auto_margins;
for (auto& item : flex_line.items) {
@ -1242,7 +1251,8 @@ void FlexFormattingContext::distribute_any_remaining_free_space()
}
// 12.2.
CSSPixels space_between_items = 0;
// CSS-FLEXBOX-2: Account for gap between items.
CSSPixels space_between_items = main_gap();
CSSPixels initial_offset = 0;
auto number_of_items = flex_line.items.size();
@ -1466,6 +1476,9 @@ void FlexFormattingContext::align_all_flex_lines()
for (auto& line : m_flex_lines)
sum_of_flex_line_cross_sizes += line.cross_size;
// CSS-FLEXBOX-2: Account for gap between flex lines.
sum_of_flex_line_cross_sizes += cross_gap() * (m_flex_lines.size() - 1);
CSSPixels start_of_current_line = 0;
CSSPixels gap_size = 0;
switch (flex_container().computed_values().align_content()) {
@ -1513,6 +1526,8 @@ void FlexFormattingContext::align_all_flex_lines()
item.cross_offset += center_of_current_line;
}
start_of_current_line += flex_line.cross_size + gap_size;
// CSS-FLEXBOX-2: Account for gap between flex lines.
start_of_current_line += cross_gap();
}
}
}
@ -1672,6 +1687,8 @@ CSSPixels FlexFormattingContext::calculate_intrinsic_main_size_of_flex_container
sum += result;
}
// CSS-FLEXBOX-2: Account for gap between flex items.
sum += main_gap() * (flex_line.items.size() - 1);
largest_sum = max(largest_sum, sum);
}
// 5. The flex containers max-content size is the largest sum (among all the lines) of the afore-calculated sizes of all items within a single line.
@ -1747,6 +1764,8 @@ CSSPixels FlexFormattingContext::calculate_intrinsic_cross_size_of_flex_containe
for (auto& flex_line : m_flex_lines) {
sum_of_flex_line_cross_sizes += flex_line.cross_size;
}
// CSS-FLEXBOX-2: Account for gap between flex lines.
sum_of_flex_line_cross_sizes += cross_gap() * (m_flex_lines.size() - 1);
return sum_of_flex_line_cross_sizes;
}
@ -2138,4 +2157,18 @@ float FlexFormattingContext::FlexLine::sum_of_scaled_flex_shrink_factor_of_unfro
return sum;
}
CSSPixels FlexFormattingContext::main_gap() const
{
auto const& computed_values = flex_container().computed_values();
auto gap = is_row_layout() ? computed_values.column_gap() : computed_values.row_gap();
return gap.resolved(flex_container(), CSS::Length::make_px(inner_main_size(flex_container()))).to_px(flex_container());
}
CSSPixels FlexFormattingContext::cross_gap() const
{
auto const& computed_values = flex_container().computed_values();
auto gap = is_row_layout() ? computed_values.row_gap() : computed_values.column_gap();
return gap.resolved(flex_container(), CSS::Length::make_px(inner_cross_size(flex_container()))).to_px(flex_container());
}
}