diff --git a/Tests/LibWeb/Ref/positioned-elements-in-scroll-container.html b/Tests/LibWeb/Ref/positioned-elements-in-scroll-container.html new file mode 100644 index 0000000000..76d9c181a3 --- /dev/null +++ b/Tests/LibWeb/Ref/positioned-elements-in-scroll-container.html @@ -0,0 +1,73 @@ + + + +
+
+

Fly away to victory!

+ +
+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat + non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+ +
A card!
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat + non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat + non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+
+
+
+ + diff --git a/Tests/LibWeb/Ref/reference/positioned-elements-in-scroll-container-ref.html b/Tests/LibWeb/Ref/reference/positioned-elements-in-scroll-container-ref.html new file mode 100644 index 0000000000..17f63ff9c0 --- /dev/null +++ b/Tests/LibWeb/Ref/reference/positioned-elements-in-scroll-container-ref.html @@ -0,0 +1,71 @@ + + + +
+
+

Fly away to victory!

+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute + irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum. +

+ +
A card!
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute + irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute + irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum. +

+
+
+ + diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index 9d5d50368c..916110ae4e 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -850,4 +850,15 @@ Optional PaintableWithLines::hit_test(CSSPixelPoint position, Hit return {}; } +PaintableBox const* PaintableBox::nearest_scrollable_ancestor() const +{ + auto* ancestor = parent(); + while (ancestor) { + if (ancestor->is_paintable_box() && static_cast(ancestor)->has_scrollable_overflow()) + return static_cast(ancestor); + ancestor = ancestor->parent(); + } + return nullptr; +} + } diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index 094d0512ea..82cf7b786a 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -191,6 +191,8 @@ public: BorderRadiiData const& border_radii_data() const { return m_border_radii_data; } void set_border_radii_data(BorderRadiiData const& border_radii_data) { m_border_radii_data = border_radii_data; } + PaintableBox const* nearest_scrollable_ancestor() const; + protected: explicit PaintableBox(Layout::Box const&); diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp index 837a48693b..62ce434ca9 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp @@ -226,6 +226,13 @@ void StackingContext::paint_internal(PaintContext& context) const : TraversalDecision::Continue; } + // Apply scroll offset of nearest scrollable ancestor before painting the positioned descendant. + PaintableBox const* nearest_scrollable_ancestor = nullptr; + if (paintable.is_paintable_box()) + nearest_scrollable_ancestor = static_cast(paintable).nearest_scrollable_ancestor(); + if (nearest_scrollable_ancestor) + nearest_scrollable_ancestor->apply_scroll_offset(context, PaintPhase::Foreground); + // At this point, `paintable_box` is a positioned descendant with z-index: auto. // FIXME: This is basically duplicating logic found elsewhere in this same function. Find a way to make this more elegant. auto exit_decision = TraversalDecision::Continue; @@ -247,6 +254,9 @@ void StackingContext::paint_internal(PaintContext& context) const if (containing_block_paintable) containing_block_paintable->clear_clip_overflow_rect(context, PaintPhase::Foreground); + if (nearest_scrollable_ancestor) + nearest_scrollable_ancestor->reset_scroll_offset(context, PaintPhase::Foreground); + return exit_decision; });