mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-08 06:09:58 +00:00
LibWeb: Support percentage values in min/max flex item size constraints
Originally,7200b3a16cintroduced a two-pass system to determine hypothetical cross sizes. Later, this was partially reverted in0084d992d4, but some code was left behind that caused resolution of percentages in `{min/max}-{width/height}` size constraints not to work. Through intrinsic sizing, we can potentially end up with a definite available space for the items in the last FC run. At that point we should be able to resolve percentages against the available space, but we were never doing that.
This commit is contained in:
parent
4ff17fc8d7
commit
3741d3040c
Notes:
github-actions[bot]
2025-11-05 11:02:42 +00:00
Author: https://github.com/gmta
Commit: 3741d3040c
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6695
Reviewed-by: https://github.com/awesomekling ✅
5 changed files with 47 additions and 24 deletions
|
|
@ -155,9 +155,8 @@ void FlexFormattingContext::run(AvailableSpace const& available_space)
|
|||
|
||||
// Cross Size Determination
|
||||
// 7. Determine the hypothetical cross size of each item
|
||||
for (auto& item : m_flex_items) {
|
||||
determine_hypothetical_cross_size_of_item(item, false);
|
||||
}
|
||||
for (auto& item : m_flex_items)
|
||||
determine_hypothetical_cross_size_of_item(item);
|
||||
|
||||
// 8. Calculate the cross size of each flex line.
|
||||
calculate_cross_size_of_each_flex_line();
|
||||
|
|
@ -1133,27 +1132,19 @@ void FlexFormattingContext::resolve_flexible_lengths()
|
|||
}
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/css-flexbox-1/#hypothetical-cross-size
|
||||
void FlexFormattingContext::determine_hypothetical_cross_size_of_item(FlexItem& item, bool resolve_percentage_min_max_sizes)
|
||||
// https://drafts.csswg.org/css-flexbox/#hypothetical-cross-size
|
||||
void FlexFormattingContext::determine_hypothetical_cross_size_of_item(FlexItem& item)
|
||||
{
|
||||
// Determine the hypothetical cross size of each item by performing layout
|
||||
// as if it were an in-flow block-level box with the used main size
|
||||
// and the given available space, treating auto as fit-content.
|
||||
// Determine the hypothetical cross size of each item by performing layout as if it were an in-flow block-level box
|
||||
// with the used main size and the given available space, treating auto as fit-content.
|
||||
|
||||
auto const& computed_min_size = this->computed_cross_min_size(item.box);
|
||||
auto const& computed_max_size = this->computed_cross_max_size(item.box);
|
||||
|
||||
auto clamp_min = (!computed_min_size.is_auto() && (resolve_percentage_min_max_sizes || !computed_min_size.contains_percentage())) ? specified_cross_min_size(item) : 0;
|
||||
auto clamp_max = (!should_treat_cross_max_size_as_none(item.box) && (resolve_percentage_min_max_sizes || !computed_max_size.contains_percentage())) ? specified_cross_max_size(item) : CSSPixels::max();
|
||||
auto clamp_min = computed_min_size.is_auto() ? 0 : specified_cross_min_size(item);
|
||||
auto clamp_max = should_treat_cross_max_size_as_none(item.box) ? CSSPixels::max() : specified_cross_max_size(item);
|
||||
|
||||
// If we have a definite cross size, this is easy! No need to perform layout, we can just use it as-is.
|
||||
if (has_definite_cross_size(item)) {
|
||||
// To avoid subtracting padding and border twice for `box-sizing: border-box` only min and max clamp should happen on a second pass
|
||||
if (resolve_percentage_min_max_sizes) {
|
||||
item.hypothetical_cross_size = css_clamp(item.hypothetical_cross_size, clamp_min, clamp_max);
|
||||
return;
|
||||
}
|
||||
|
||||
item.hypothetical_cross_size = css_clamp(inner_cross_size(item), clamp_min, clamp_max);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1946,9 +1937,8 @@ CSSPixels FlexFormattingContext::calculate_intrinsic_cross_size_of_flex_containe
|
|||
// https://drafts.csswg.org/css-flexbox-1/#intrinsic-item-contributions
|
||||
CSSPixels FlexFormattingContext::calculate_main_min_content_contribution(FlexItem const& item) const
|
||||
{
|
||||
// The main-size min-content contribution of a flex item is
|
||||
// the larger of its outer min-content size and outer preferred size if that is not auto,
|
||||
// clamped by its min/max main size.
|
||||
// The main-size min-content contribution of a flex item is the larger of its outer min-content size and outer
|
||||
// preferred size if that is not auto, clamped by its min/max main size.
|
||||
auto larger_size = [&] {
|
||||
auto inner_min_content_size = calculate_min_content_main_size(item);
|
||||
if (computed_main_size(item.box).is_auto())
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ private:
|
|||
|
||||
void resolve_cross_axis_auto_margins();
|
||||
|
||||
void determine_hypothetical_cross_size_of_item(FlexItem&, bool resolve_percentage_min_max_sizes);
|
||||
void determine_hypothetical_cross_size_of_item(FlexItem&);
|
||||
|
||||
void calculate_cross_size_of_each_flex_line();
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,8 @@ public:
|
|||
|
||||
virtual void run(AvailableSpace const&) = 0;
|
||||
|
||||
// This function returns the automatic content height of the context's root box.
|
||||
// These functions return the automatic content dimensions of the context's root box.
|
||||
virtual CSSPixels automatic_content_width() const = 0;
|
||||
|
||||
// This function returns the automatic content height of the context's root box.
|
||||
virtual CSSPixels automatic_content_height() const = 0;
|
||||
|
||||
Box const& context_box() const { return m_context_box; }
|
||||
|
|
|
|||
17
Tests/LibWeb/Layout/expected/flex/nested-min-width-item.txt
Normal file
17
Tests/LibWeb/Layout/expected/flex/nested-min-width-item.txt
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not-inline
|
||||
BlockContainer <html> at [0,0] [0+0+0 800 0+0+0] [0+0+0 41 0+0+0] [BFC] children: not-inline
|
||||
BlockContainer <body> at [8,8] [8+0+0 784 0+0+8] [8+0+0 25 0+0+8] children: not-inline
|
||||
Box <div.a> at [8,8] flex-container(column) [0+0+0 784 0+0+0] [0+0+0 25 0+0+0] [FFC] children: not-inline
|
||||
BlockContainer <div.b> at [8,8] flex-item [0+0+0 784 0+0+0] [0+0+0 25 0+0+0] [BFC] children: not-inline
|
||||
BlockContainer <div.c> at [8,8] [0+0+0 50 0+0+734] [0+0+0 25 0+0+0] children: inline
|
||||
TextNode <#text> (not painted)
|
||||
|
||||
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||
PaintableWithLines (BlockContainer<HTML>) [0,0 800x41]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,8 784x25]
|
||||
PaintableBox (Box<DIV>.a) [8,8 784x25]
|
||||
PaintableWithLines (BlockContainer<DIV>.b) [8,8 784x25]
|
||||
PaintableWithLines (BlockContainer<DIV>.c) [8,8 50x25]
|
||||
|
||||
SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto)
|
||||
SC for BlockContainer<HTML> [0,0 800x41] [children: 0] (z-index: auto)
|
||||
18
Tests/LibWeb/Layout/input/flex/nested-min-width-item.html
Normal file
18
Tests/LibWeb/Layout/input/flex/nested-min-width-item.html
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
.a {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
.b {
|
||||
background: blue;
|
||||
min-width: 100%;
|
||||
}
|
||||
.c {
|
||||
background: red;
|
||||
height: 25px;
|
||||
width: 50px;
|
||||
}
|
||||
</style>
|
||||
<div class="a"><div class="b"><div class="c">
|
||||
Loading…
Add table
Add a link
Reference in a new issue