Even if block has all children inline there need to be a check
if it creates BFC because otherwise IFC will be looking in
wrong parent BFC to calculate space used by floats.
This will make it easier to support both string types at the same time
while we convert code, and tracking down remaining uses.
One big exception is Value::to_string() in LibJS, where the name is
dictated by the ToString AO.
This change makes calculate_static_position to return content box
for both x and y (at least for the case when children are not inline).
It makes it possible to be consistent about x and y when calculating
box offset inside layout_absolutely_positioned_element.
This can resolve height early in some cases, notably this kind of setup:
position: absolute;
top: 0px;
bottom: 0px;
By resolving height before inside layout, descendants of the abspos
element can resolve automatic and relative vertical lengths against it.
This makes the Discord UI occupy the whole window instead of looking
"shrink-to-fit".
For replaced elements with percentage width or height, we were treating
them as 0 instead of auto when their containing block had an indefinite
corresponding size.
This produced incorrect layouts in various cases, and although I can't
actually find something about this exact scenario in specs, the new
behavior does match other browsers.
As it turns out, we sometimes query the intrinsic height of a box before
having fully resolved and/or constrained its containing block. Because
of this, we may enter intrinsic sizing with different amounts of
available width for the same box.
To accommodate this scenario, we now allow caching of multiple intrinsic
heights, separated by the amount of available width provided as input.
We were using the available space in place of the stretch-fit size.
This was an oversight, and this patch fixes that. It's very possible
that this will uncover broken behavior elsewhere.
This refactors the solve_for_{top, bottom, height, etc} lambdas to use a
common solve_for lambda that takes the length to be solved as an
argument. This way some code duplication is removed.
This patch implements the full "old model" height algorithm from the
CSS Positioned Layout spec. I went with the old model since we don't
yet have the machinery required to implement the new model.
Also, the width calculations already follow the old model, so this
is symmetric with that. Eventually we should of course implement the new
positioned layout model.
Now that intrinsic heights (correctly) depend on the amount of available
width, we can't just cache the first calculated min-content and
max-content heights and reuse it without thinking.
Instead, we have to cache three pairs:
- min-content & max-content height with definite available width
- min-content & max-content height with min-content available width
- min-content & max-content height with max-content available width
There might be some more elegant way of solving this, but basically this
makes the cache work correctly when someone's containing block is being
sized under a width constraint.
After speaking with fantasai at CSSWG about this, it turns out I had
misunderstood intrinsic heights. I originally believed all intrinsic
sizes had to be computed with no influence from the surrounding context.
As it turns out, intrinsic heights *are* influenced by the available
width, since it's needed to determine where lines break.
The APIs for calculating min-content and max-content heights now take
the available width as inputs. This instantly improves layout in many
cases where we'd previously make things way too wide.
When an absolutely positioned box has auto insets on both sides of an
axis, it's placed according to the "static position rectangle". This is,
roughly, the rectangle a box would occupy if it were position:static
instead of position:absolute or position:fixed.
This patch implements a rough, but still significantly better,
estimation of such static positions. It gets pretty hairy in the case
where an abspos box has a parent whose children are inline.
This is a big and messy change, and here's the gist:
- AvaliableSpace is now 2x AvailableSize (width and height)
- Layout algorithms are redesigned around the idea of available space
- When doing layout across nested formatting contexts, the parent
context tells the child context how much space is available for the
child's root box in both axes.
- "Available space" replaces "containing block width" in most places.
- The width and height in a box's UsedValues are considered to be
definite after they're assigned to. Marking something as having
definite size is no longer a separate step,
This probably introduces various regressions, but the big win here is
that our layout system now works with available space, just like the
specs are written. Fixing issues will be much easier going forward,
since you don't need to do nearly as much conversion from "spec logic"
to "LibWeb logic" as you previously did.
If a flex item is itself a flex container, we were previously lying when
asked if the item created a BFC. It creates an FFC, so stop lying about
this in FormattingContext::creates_block_formatting_context().
Instead of formatting contexts flailing around to figure out from the
"inside" how much space is available on the "outside", we should
provide the amount of available space in both axes as an input to run().
This basically means that when something creates a nested formatting
context, the parent context is responsible for telling the nested context
how much space is available for layout. This information is provided
immediately when invoking run().
Note that this commit doesn't pass accurate values in all cases yet.
This first step just makes it build, and passes available values in some
cases where getting them was trivial.
This patch changes the *computed* representation of the following CSS
properties to use CSS::Size:
- width, min-width, max-width
- height, min-height, max-height
A few things had to change in order for things to keep working,
but I tried to keep the diff to a minimum.
The main trouble was that `min-width` and `max-width` can't actually be
`auto`, but they *can* be `none`. We previously treated `auto` as a
valid value (and it behaved mostly like `none`).
This function should return the automatic height of the formatting
context's root box.
Until now, we've been relying on some magical handshakes between parent
and child context, when negotiating the height of child context root
boxes. This is a step towards something more reasonable.
This remained undetected for a long time as HeaderCheck is disabled by
default. This commit makes the following file compile again:
// file: compile_me.cpp
#include <LibWeb/CSS/GridTrackSize.h>
// That's it, this was enough to cause a compilation error.
When calculating the automatic height of a BFC root, we stretch it to
contain the bottommost margin edge of floating boxes.
Before this change, we assumed that floating boxes had coordinates
relative to the BFC root, when they're actually relative to the floating
box's containing block. This may or may not be the BFC root, so we have
to use margin_box_in_ancestor_coordinate_space() to apply offsets from
all boxes in the containing block chain (up to the BFC root).
Before this change, block-level boxes were laid out vertically by
placing them after the nearest previous BlockContainer sibling. This
only worked if the preceding block-level box happened to be a
BlockContainer.
This fixes an issue where the screenshot on netsurf-browser.org was not
being laid out properly (it was `img { display: block }` which creates
a block-level ImageBox, and ImageBox is not a BlockContainer but a
ReplacedBox, so the following block-level box was skipping over the
ImageBox and being placed next to whatever was before the ImageBox..)