From 06d05b3c55325b095e76a2529bbf1be88f7e9aae Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Fri, 22 Sep 2023 15:33:25 +0200 Subject: [PATCH] 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 --- ...tainer-should-avoid-overlapping-floats.txt | 23 +++++++++++++++++++ ...tainer-should-avoid-overlapping-floats.txt | 16 +++++++++++++ ...ainer-should-avoid-overlapping-floats.html | 14 +++++++++++ ...ainer-should-avoid-overlapping-floats.html | 13 +++++++++++ .../LibWeb/Layout/BlockFormattingContext.cpp | 17 +++++++++++++- .../LibWeb/Layout/BlockFormattingContext.h | 1 + 6 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 Tests/LibWeb/Layout/expected/block-and-inline/flex-container-should-avoid-overlapping-floats.txt create mode 100644 Tests/LibWeb/Layout/expected/block-and-inline/grid-container-should-avoid-overlapping-floats.txt create mode 100644 Tests/LibWeb/Layout/input/block-and-inline/flex-container-should-avoid-overlapping-floats.html create mode 100644 Tests/LibWeb/Layout/input/block-and-inline/grid-container-should-avoid-overlapping-floats.html diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/flex-container-should-avoid-overlapping-floats.txt b/Tests/LibWeb/Layout/expected/block-and-inline/flex-container-should-avoid-overlapping-floats.txt new file mode 100644 index 00000000000..0b984d76f36 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/block-and-inline/flex-container-should-avoid-overlapping-floats.txt @@ -0,0 +1,23 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x66 [BFC] children: not-inline + BlockContainer at (8,8) content-size 400x50 children: not-inline + BlockContainer 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 at (8,8) content-size 362.890625x50 flex-container(row) [FFC] children: not-inline + BlockContainer 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) [0,0 800x66] + PaintableWithLines (BlockContainer) [8,8 400x50] + PaintableWithLines (BlockContainer
.right) [370.890625,8 37.109375x17.46875] + TextPaintable (TextNode<#text>) + PaintableBox (Box
.flex) [8,8 362.890625x50] + PaintableWithLines (BlockContainer
.item) [8,8 32.34375x50] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/grid-container-should-avoid-overlapping-floats.txt b/Tests/LibWeb/Layout/expected/block-and-inline/grid-container-should-avoid-overlapping-floats.txt new file mode 100644 index 00000000000..18062654d19 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/block-and-inline/grid-container-should-avoid-overlapping-floats.txt @@ -0,0 +1,16 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x66 [BFC] children: not-inline + BlockContainer at (8,8) content-size 400x50 children: not-inline + BlockContainer 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 at (8,8) content-size 362.890625x50 [GFC] children: not-inline + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x66] + PaintableWithLines (BlockContainer) [8,8 400x50] + PaintableWithLines (BlockContainer
.right) [370.890625,8 37.109375x17.46875] + TextPaintable (TextNode<#text>) + PaintableBox (Box
.grid) [8,8 362.890625x50] diff --git a/Tests/LibWeb/Layout/input/block-and-inline/flex-container-should-avoid-overlapping-floats.html b/Tests/LibWeb/Layout/input/block-and-inline/flex-container-should-avoid-overlapping-floats.html new file mode 100644 index 00000000000..bc3fe78906d --- /dev/null +++ b/Tests/LibWeb/Layout/input/block-and-inline/flex-container-should-avoid-overlapping-floats.html @@ -0,0 +1,14 @@ +
right
item \ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/block-and-inline/grid-container-should-avoid-overlapping-floats.html b/Tests/LibWeb/Layout/input/block-and-inline/grid-container-should-avoid-overlapping-floats.html new file mode 100644 index 00000000000..dbacfe71bed --- /dev/null +++ b/Tests/LibWeb/Layout/input/block-and-inline/grid-container-should-avoid-overlapping-floats.html @@ -0,0 +1,13 @@ +
right
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index 432ebf31382..ff101f941ec 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -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 diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h index a2014cc56bf..eec02a897be 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h @@ -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