diff options
author | Andreas Kling <kling@serenityos.org> | 2023-04-14 10:35:26 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-04-14 13:22:07 +0200 |
commit | 47c21cc3497066c0227268879ac4351d1975d2db (patch) | |
tree | 968e1843977ac213f6d5082104222ac4338f8f0f /Userland/Libraries/LibWeb | |
parent | 7dd3c4a79c2a1d937eff90729bcbb6b47cb007b1 (diff) | |
download | serenity-47c21cc3497066c0227268879ac4351d1975d2db.zip |
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.
Diffstat (limited to 'Userland/Libraries/LibWeb')
-rw-r--r-- | Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp | 35 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h | 2 |
2 files changed, 36 insertions, 1 deletions
diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index f2636de719..999e8185b3 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -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 container’s 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()); +} + } diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h index 383c2acd06..5d36ef3691 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h @@ -112,6 +112,8 @@ private: float sum_of_scaled_flex_shrink_factor_of_unfrozen_items() const; }; + CSSPixels main_gap() const; + CSSPixels cross_gap() const; bool has_definite_main_size(Box const&) const; bool has_definite_cross_size(Box const&) const; CSSPixels inner_main_size(Box const&) const; |