From a87f7b9561a12914395a2e47cb29e0c4cd7b6689 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Mon, 22 Jun 2026 09:00:28 +0100 Subject: [PATCH] LibWeb: Account for visual viewport when scrolling a target into view This ensures the correct portion of the screen is scrolled into view when the window is pinch-zoomed. --- Libraries/LibWeb/DOM/Element.cpp | 14 ++++-- .../scroll-into-view-with-pinch-zoom.txt | 2 + .../scroll-into-view-with-pinch-zoom.html | 43 +++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/scroll-into-view-with-pinch-zoom.txt create mode 100644 Tests/LibWeb/Text/input/scroll-into-view-with-pinch-zoom.html diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index a3069538c8..da23181888 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -2896,9 +2897,16 @@ static CSSPixelPoint determine_the_scroll_into_view_position(Element& target, Bi CSSPixelRect scrolling_box_rect; CSSPixelPoint current_scroll_position; if (scrolling_box.is_document()) { - // NOTE: Element::getBoundingClientRect() returns coordinates relative to the viewport. - scrolling_box_rect = { {}, scrolling_box.document().viewport_rect().size() }; - current_scroll_position = scrolling_box.document().navigable()->viewport_scroll_offset(); + auto& document = scrolling_box.document(); + auto& visual_viewport = *document.visual_viewport(); + // NB: Use the visual viewport as the scrolling box, this ensures that the target is scrolled into the visible + // region on screen when the page is pinch-zoomed. + CSSPixelSize visible_size { + CSSPixels::nearest_value_for(visual_viewport.width()), + CSSPixels::nearest_value_for(visual_viewport.height()), + }; + scrolling_box_rect = { visual_viewport.offset(), visible_size }; + current_scroll_position = document.navigable()->viewport_scroll_offset() + visual_viewport.offset(); } else if (auto paintable_box = scrolling_box.paintable_box()) { current_scroll_position = paintable_box->scroll_offset(); scrolling_box_rect = paintable_box->absolute_rect(); diff --git a/Tests/LibWeb/Text/expected/scroll-into-view-with-pinch-zoom.txt b/Tests/LibWeb/Text/expected/scroll-into-view-with-pinch-zoom.txt new file mode 100644 index 0000000000..2a7a543d4a --- /dev/null +++ b/Tests/LibWeb/Text/expected/scroll-into-view-with-pinch-zoom.txt @@ -0,0 +1,2 @@ +target visible before scrollIntoView: false +target visible after scrollIntoView: true diff --git a/Tests/LibWeb/Text/input/scroll-into-view-with-pinch-zoom.html b/Tests/LibWeb/Text/input/scroll-into-view-with-pinch-zoom.html new file mode 100644 index 0000000000..e3caeaf58c --- /dev/null +++ b/Tests/LibWeb/Text/input/scroll-into-view-with-pinch-zoom.html @@ -0,0 +1,43 @@ + + +
+
+ +