LibWeb: Boxes that establish FFC or GFC should avoid overlapping floats

Before, we only ensured that boxes establishing BFC did not overlap
with floats because that is what CSS 2.2 specification says. However,
we should also apply the same for boxes establishing FFC or GFC as this
aligns with the behavior of other browsers.

Fixes https://github.com/SerenityOS/serenity/issues/21095
This commit is contained in:
Aliaksandr Kalenik 2023-09-22 15:33:25 +02:00 committed by Andreas Kling
parent 1cfaadec02
commit 06d05b3c55
Notes: sideshowbarker 2024-07-18 22:57:59 +09:00
6 changed files with 83 additions and 1 deletions

View file

@ -0,0 +1,23 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x66 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 400x50 children: not-inline
BlockContainer <div.right> at (370.890625,8) content-size 37.109375x17.46875 floating [BFC] children: inline
line 0 width: 37.109375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
frag 0 from TextNode start: 0, length: 5, rect: [370.890625,8 37.109375x17.46875]
"right"
TextNode <#text>
Box <div.flex> at (8,8) content-size 362.890625x50 flex-container(row) [FFC] children: not-inline
BlockContainer <div.item> at (8,8) content-size 32.34375x50 flex-item [BFC] children: inline
line 0 width: 32.34375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
frag 0 from TextNode start: 0, length: 4, rect: [8,8 32.34375x17.46875]
"item"
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x66]
PaintableWithLines (BlockContainer<BODY>) [8,8 400x50]
PaintableWithLines (BlockContainer<DIV>.right) [370.890625,8 37.109375x17.46875]
TextPaintable (TextNode<#text>)
PaintableBox (Box<DIV>.flex) [8,8 362.890625x50]
PaintableWithLines (BlockContainer<DIV>.item) [8,8 32.34375x50]
TextPaintable (TextNode<#text>)

View file

@ -0,0 +1,16 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x66 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 400x50 children: not-inline
BlockContainer <div.right> at (370.890625,8) content-size 37.109375x17.46875 floating [BFC] children: inline
line 0 width: 37.109375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
frag 0 from TextNode start: 0, length: 5, rect: [370.890625,8 37.109375x17.46875]
"right"
TextNode <#text>
Box <div.grid> at (8,8) content-size 362.890625x50 [GFC] children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x66]
PaintableWithLines (BlockContainer<BODY>) [8,8 400x50]
PaintableWithLines (BlockContainer<DIV>.right) [370.890625,8 37.109375x17.46875]
TextPaintable (TextNode<#text>)
PaintableBox (Box<DIV>.grid) [8,8 362.890625x50]

View file

@ -0,0 +1,14 @@
<!doctype html><style>
* { outline: 1px solid black; }
body { width: 400px; }
.right {
float: right;
background: orange;
}
.flex {
display: flex;
height: 50px;
background: wheat;
}
.item { background: pink; }
</style><body><div class="right">right</div><div class="flex"><div class="item">item

View file

@ -0,0 +1,13 @@
<!doctype html><style>
* { outline: 1px solid black; }
body { width: 400px; }
.right {
float: right;
background: orange;
}
.grid {
display: grid;
height: 50px;
background: wheat;
}
</style><body><div class="right">right</div><div class="grid">

View file

@ -117,6 +117,19 @@ void BlockFormattingContext::parent_context_did_dimension_child_root_box()
}
}
bool BlockFormattingContext::box_should_avoid_floats_because_it_establishes_fc(Box const& box)
{
if (auto formatting_context_type = formatting_context_type_created_by_box(box); formatting_context_type.has_value()) {
if (formatting_context_type.value() == Type::Block)
return true;
if (formatting_context_type.value() == Type::Flex)
return true;
if (formatting_context_type.value() == Type::Grid)
return true;
}
return false;
}
void BlockFormattingContext::compute_width(Box const& box, AvailableSpace const& available_space, LayoutMode)
{
if (box.is_absolutely_positioned()) {
@ -125,7 +138,9 @@ void BlockFormattingContext::compute_width(Box const& box, AvailableSpace const&
}
auto remaining_available_space = available_space;
if (available_space.width.is_definite() && creates_block_formatting_context(box)) {
if (available_space.width.is_definite() && box_should_avoid_floats_because_it_establishes_fc(box)) {
// NOTE: Although CSS 2.2 specification says that only block formatting contexts should avoid floats,
// we also do this for flex and grid formatting contexts, because that how other engines behave.
// 9.5 Floats
// The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a
// new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap the margin

View file

@ -29,6 +29,7 @@ public:
auto const& left_side_floats() const { return m_left_floats; }
auto const& right_side_floats() const { return m_right_floats; }
bool box_should_avoid_floats_because_it_establishes_fc(Box const&);
void compute_width(Box const&, AvailableSpace const&, LayoutMode = LayoutMode::Normal);
// https://www.w3.org/TR/css-display/#block-formatting-context-root