diff --git a/Tests/LibWeb/Layout/expected/viewport-overflow-propagation-1.txt b/Tests/LibWeb/Layout/expected/viewport-overflow-propagation-1.txt new file mode 100644 index 0000000000..fdb512c771 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/viewport-overflow-propagation-1.txt @@ -0,0 +1,10 @@ +Viewport <#document> at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (0,0) content-size 800x2016 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x2000 children: not-inline + BlockContainer
at (8,8) content-size 100x2000 children: inline + TextNode <#text> + +PaintableWithLines (Viewport<#document>) [0,0 800x600] overflow: [0,0 800x2016] + PaintableWithLines (BlockContainer) [0,0 800x2016] + PaintableWithLines (BlockContainer) [8,8 784x2000] + PaintableWithLines (BlockContainer
) [8,8 100x2000] diff --git a/Tests/LibWeb/Layout/expected/viewport-overflow-propagation-2.txt b/Tests/LibWeb/Layout/expected/viewport-overflow-propagation-2.txt new file mode 100644 index 0000000000..f58bb6c517 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/viewport-overflow-propagation-2.txt @@ -0,0 +1,10 @@ +Viewport <#document> at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (0,0) content-size 800x616 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x600 children: not-inline + BlockContainer at (8,8) content-size 784x2000 children: inline + TextNode <#text> + +PaintableWithLines (Viewport<#document>) [0,0 800x600] overflow: [0,0 800x2008] + PaintableWithLines (BlockContainer) [0,0 800x616] overflow: [0,0 800x2008] + PaintableWithLines (BlockContainer) [8,8 784x600] overflow: [8,8 784x2000] + PaintableWithLines (BlockContainer
.long) [8,8 784x2000] diff --git a/Tests/LibWeb/Layout/input/viewport-overflow-propagation-1.html b/Tests/LibWeb/Layout/input/viewport-overflow-propagation-1.html new file mode 100644 index 0000000000..1687d10874 --- /dev/null +++ b/Tests/LibWeb/Layout/input/viewport-overflow-propagation-1.html @@ -0,0 +1,12 @@ +
diff --git a/Tests/LibWeb/Layout/input/viewport-overflow-propagation-2.html b/Tests/LibWeb/Layout/input/viewport-overflow-propagation-2.html new file mode 100644 index 0000000000..431333e119 --- /dev/null +++ b/Tests/LibWeb/Layout/input/viewport-overflow-propagation-2.html @@ -0,0 +1,10 @@ +
diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 1a4df62a65..a6cef56816 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -917,6 +917,38 @@ void Document::invalidate_layout() schedule_layout_update(); } +static void propagate_overflow_to_viewport(Element& root_element, Layout::Viewport& viewport) +{ + // https://drafts.csswg.org/css-overflow-3/#overflow-propagation + // UAs must apply the overflow-* values set on the root element to the viewport + // when the root element’s display value is not none. + auto* overflow_origin_node = root_element.layout_node(); + auto& viewport_computed_values = const_cast(static_cast(static_cast(viewport.computed_values()))); + + // However, when the root element is an [HTML] html element (including XML syntax for HTML) + // whose overflow value is visible (in both axes), and that element has as a child + // a body element whose display value is also not none, + // user agents must instead apply the overflow-* values of the first such child element to the viewport. + if (root_element.is_html_html_element()) { + auto* root_element_layout_node = root_element.layout_node(); + auto& root_element_computed_values = const_cast(static_cast(static_cast(root_element_layout_node->computed_values()))); + if (root_element_computed_values.overflow_x() == CSS::Overflow::Visible && root_element_computed_values.overflow_y() == CSS::Overflow::Visible) { + auto* body_element = root_element.first_child_of_type(); + if (body_element && body_element->layout_node()) + overflow_origin_node = body_element->layout_node(); + } + } + + // NOTE: This is where we assign the chosen overflow values to the viewport. + auto& overflow_origin_computed_values = const_cast(static_cast(static_cast(overflow_origin_node->computed_values()))); + viewport_computed_values.set_overflow_x(overflow_origin_computed_values.overflow_x()); + viewport_computed_values.set_overflow_y(overflow_origin_computed_values.overflow_y()); + + // The element from which the value is propagated must then have a used overflow value of visible. + overflow_origin_computed_values.set_overflow_x(CSS::Overflow::Visible); + overflow_origin_computed_values.set_overflow_y(CSS::Overflow::Visible); +} + void Document::update_layout() { // NOTE: If our parent document needs a relayout, we must do that *first*. @@ -943,6 +975,8 @@ void Document::update_layout() m_layout_root = verify_cast(*tree_builder.build(*this)); } + propagate_overflow_to_viewport(*document_element(), *m_layout_root); + Layout::LayoutState layout_state; {