In situations where we need a width to calculate the intrinsic height of
a flex item, we use the fit-content width as a stand-in. However, we
also need to clamp it to any min-width and max-width properties present.
In `flex-direction: column` layouts, a flex item's intrinsic height may
depend on its width, but the width is calculated *after* the intrinsic
height is required.
Unfortunately, the specification doesn't tell us exactly what to do here
(missing inputs to intrinsic sizing is a common problem) so we take the
solution that flexbox applies in 9.2.3.C and apply it to all intrinsic
height calculations within FlexFormattingContext: if the used width of
an item is not yet known when its intrinsic height is requested, we
substitute the fit-content width instead.
Note that while this is technically ad-hoc, it's basically extrapolating
the spec's suggestion in one specific case and using it in all cases.
The "flex item automatic minimum size in the main axis is the
content-based minimum size" behavior should only apply to flex item
sizes in the main axis. There was one case where we incorrectly applied
this behavior in the cross axis
The "flex item automatic minimum size in the main axis is the
content-based minimum size" behavior should only apply to flex items
that aren't scroll containers. We were doing it for all flex items.
When calculating one of the intrinsic sizes for a flex container, we
already go through the flex layout algorithm.
There's no need to perform some of the algorithm steps a second time.
This is a relic from an earlier time when we tried to bail early from
the layout algorithm in the intrinsic sizing case. Now that we go
through the whole thing anyway, this is much simpler. :^)
Instead of special-casing FlexFormattingContext in the intrinsic sizing
layout helpers, add FormattingContext::automatic_content_width() and let
each context subclass decide what that means.
No behavior change here, just moving this responsibility.
This fixes an issue where e.g `height: 100%` on a flex item whose
container has indefinite height was being resolved to 0. It now
correctly behaves the same as auto.
When we're calculating the intrinsic size of a flex container, we don't
*need* to layout the inside of each flex item. That's only necessary if
the flex items will be seen (as is the case for "normal" layout).
This avoids a whole bunch of unnecessary layout work on pages that use
flexbox layout. :^)
When using the flex shrink factor, the flexible length resolution
algorithm was incorrectly ignoring the `frozen` flag on items and would
update the same items again, causing overconsumption of the remaining
free space on the flex line.
In case flex items had `margin: auto` on the primary flex axis, we were
still also distributing remaining space according to `justify-content`
rules. This lead to duplicated spacing in various places and overflows.
It looks like this issue was observed previously but missidentified
because there was logic to ignore margins at the start and end which
would partially paper over the root cause. However this created other
bugs (like for example not having a margin at beginning and end ;-)) and
I can find nothing in the spec or other browser behaviour that indicates
that this is something that should be done.
Now we skip justify-content space distribution alltogether if it has
already been distributed to auto margins.
The draft CSS-FLEXBOX-1 spec had a more detailed description of this
algorithm, so let's use that as our basis for the implementation.
Test by Aliaksandr. :^)
When resolving these constraints to CSS pixel sizes, we have to resolve
padding-top and padding-bottom against the flex container's *width*,
not its height.
This was necessary in the past, because IFC would set the height of its
containing block after inline layout.
Now that IFC can properly communicate the automatic size to its parent
formatting context, this hack is no longer necessary.
"Specified" means something else in CSS, so let's not use this
overloaded word here. These helpers return the inner main/cross size of
a given box, so let's say "inner" instead.
The name "initial containing block" was wrong for this, as it doesn't
correspond to the HTML element, and that's specifically what it's
supposed to do! :^)
We were incorrectly using the inner main size of the flex container
instead of the avilable space in some parts of the remaining space
calculation. This meant that the algorithm only worked correctly
for definite available space in the main axis.
If we've already established the used width for a flex item, we need
to take it into account when calculating the min-content and max-content
heights for that item.
We were already doing this when calculating cross sizes. This patch adds
the same consideration for main sizes.
When calculating intrinsic heights of flex items, we should use the used
width if available.
This primarily matters for item cross sizing, since that happens after
we've determined the item's main size.
We were trying to take a shortcut by avoiding much of the flex layout
algorithm during intrinsic sizing. Unfortunately, this isn't good enough
since we may end up needing some of the flex item metrics for intrinsic
contribution calculations.
This means we do a bit more work for flexboxes, but intrinsic sizes are
correct in more cases.
When a flex item has a specific preferred size, that size should be its
contribution to the containers intrinsic sizes.
This fixes an issue on Patreon where the logo would cover the entire
viewport since the SVG had a large intrinsic size but the flex item
containing it had a small specified size in CSS.
This colors a bit outside the lines of the specification, but the spec
doesn't offer a proper explanation for how descendants of a flex item
are supposed to have access to the flex item's main size for purposes
of percentage resolution.
The approach I came up with here was to take the hypothetical main size
of each flex item, and assign it as a temporary main size. This allows
percentage resolution in descendants to work against the pre-flexing
main size of items. This seems to match how other engines behave,
although it feels somewhat dirty. If/when we learn more about this,
we can come up with something nicer.
This property tells us how to lay out multi-line flex containers.
I implemented all modes except `space-between` and `space-around`.
Those are left as FIXMEs.
When calculating the fit-content width or height for a flex item, we
need to use the available space *outside* the item, not the available
space *inside*.
We now know exactly how to calculate the min-content cross size for
multi-line flex containers, which is great. The other three intrinsic
constraints still fall back to the old ad-hoc code path.
5630e7b064
For percentage cross min/max sizes that resolve against indefinite
available space, we now essentially ignore them instead of resolving
them to 0 at the start of layout.
When we have nested flexbox layouts within one another, and the child
context wants to call up to the parent context and ask for help with
dimensioning the child flex container, we now simply do nothing.
As far as I can tell, this works out just fine, since the child flex
container will already be dimensioned by the flex layout algorithm.
Previously, FlexFormattingContext would calculate intrinsic sizes in
both axes simultaneously, despite only one being needed.
This patch reduces the amount of unnecessary work by only calculating
the requested intrinsic size.