From 9e4226f3539ec63c4fdd509697bbf6fad1f4c098 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 28 Sep 2022 17:11:23 +0200 Subject: [PATCH] LibWeb: Create flex items for empty generated boxes I couldn't find anything in the specs about this, but GMail uses empty generated boxes (`::before` and `::after` with `content: ""`) inside a flexbox container in order to vertically center things. The flexbox spec tells us to not generate flex items for empty *anonymous* boxes, so we continue not doing that, but generated boxes (any pseudo-element box) now always produce a flex item. This probably isn't perfect either, and we'll have to revisit it for stuff like `::first-letter`. --- Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp | 2 +- Userland/Libraries/LibWeb/Layout/Node.h | 4 ++++ Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index 6159f29dc3..5ad2d6e37e 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -291,7 +291,7 @@ void FlexFormattingContext::generate_anonymous_flex_items() flex_container().for_each_child_of_type([&](Box& child_box) { // Skip anonymous text runs that are only whitespace. - if (child_box.is_anonymous() && !child_box.first_child_of_type()) { + if (child_box.is_anonymous() && !child_box.is_generated() && !child_box.first_child_of_type()) { bool contains_only_white_space = true; child_box.for_each_in_subtree([&](auto const& node) { if (!is(node) || !static_cast(node).dom_node().data().is_whitespace()) { diff --git a/Userland/Libraries/LibWeb/Layout/Node.h b/Userland/Libraries/LibWeb/Layout/Node.h index 7fcd9c7953..ae5bb7805f 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.h +++ b/Userland/Libraries/LibWeb/Layout/Node.h @@ -41,6 +41,9 @@ public: DOM::Node const* dom_node() const; DOM::Node* dom_node(); + bool is_generated() const { return m_generated; } + void set_generated(bool b) { m_generated = b; } + Painting::Paintable* paintable() { return m_paintable; } Painting::Paintable const* paintable() const { return m_paintable; } void set_paintable(RefPtr); @@ -153,6 +156,7 @@ private: SelectionState m_selection_state { SelectionState::None }; bool m_is_flex_item { false }; + bool m_generated { false }; }; class NodeWithStyle : public Node { diff --git a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp index 02d7cb2396..2f3b00fdc7 100644 --- a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -214,6 +214,7 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& return nullptr; if (auto pseudo_element_node = DOM::Element::create_layout_node_for_display_type(document, pseudo_element_display, move(pseudo_element_style), nullptr)) { + pseudo_element_node->set_generated(true); // FIXME: Handle images, and multiple values if (pseudo_element_content.type == CSS::ContentData::Type::String) { auto* text = document.heap().allocate(document.realm(), document, pseudo_element_content.data);