diff --git a/core/src/overlay.rs b/core/src/overlay.rs
index f71f25f734..af10afee60 100644
--- a/core/src/overlay.rs
+++ b/core/src/overlay.rs
@@ -11,7 +11,7 @@ use crate::mouse;
 use crate::renderer;
 use crate::widget;
 use crate::widget::Tree;
-use crate::{Clipboard, Layout, Point, Rectangle, Shell, Size};
+use crate::{Clipboard, Layout, Point, Rectangle, Shell, Size, Vector};
 
 /// An interactive component that can be displayed on top of other widgets.
 pub trait Overlay<Message, Renderer>
@@ -29,6 +29,7 @@ where
         renderer: &Renderer,
         bounds: Size,
         position: Point,
+        translation: Vector,
     ) -> layout::Node;
 
     /// Draws the [`Overlay`] using the associated `Renderer`.
diff --git a/core/src/overlay/element.rs b/core/src/overlay/element.rs
index 3dd58f9b58..a279fe2859 100644
--- a/core/src/overlay/element.rs
+++ b/core/src/overlay/element.rs
@@ -13,6 +13,7 @@ use std::any::Any;
 #[allow(missing_debug_implementations)]
 pub struct Element<'a, Message, Renderer> {
     position: Point,
+    translation: Vector,
     overlay: Box<dyn Overlay<Message, Renderer> + 'a>,
 }
 
@@ -25,7 +26,11 @@ where
         position: Point,
         overlay: Box<dyn Overlay<Message, Renderer> + 'a>,
     ) -> Self {
-        Self { position, overlay }
+        Self {
+            position,
+            overlay,
+            translation: Vector::ZERO,
+        }
     }
 
     /// Returns the position of the [`Element`].
@@ -36,6 +41,7 @@ where
     /// Translates the [`Element`].
     pub fn translate(mut self, translation: Vector) -> Self {
         self.position = self.position + translation;
+        self.translation = self.translation + translation;
         self
     }
 
@@ -48,6 +54,7 @@ where
     {
         Element {
             position: self.position,
+            translation: self.translation,
             overlay: Box::new(Map::new(self.overlay, f)),
         }
     }
@@ -59,8 +66,12 @@ where
         bounds: Size,
         translation: Vector,
     ) -> layout::Node {
-        self.overlay
-            .layout(renderer, bounds, self.position + translation)
+        self.overlay.layout(
+            renderer,
+            bounds,
+            self.position + translation,
+            self.translation + translation,
+        )
     }
 
     /// Processes a runtime [`Event`].
@@ -154,8 +165,9 @@ where
         renderer: &Renderer,
         bounds: Size,
         position: Point,
+        translation: Vector,
     ) -> layout::Node {
-        self.content.layout(renderer, bounds, position)
+        self.content.layout(renderer, bounds, position, translation)
     }
 
     fn operate(
diff --git a/core/src/overlay/group.rs b/core/src/overlay/group.rs
index dccf6dbaca..e1e9727a40 100644
--- a/core/src/overlay/group.rs
+++ b/core/src/overlay/group.rs
@@ -4,7 +4,9 @@ use crate::mouse;
 use crate::overlay;
 use crate::renderer;
 use crate::widget;
-use crate::{Clipboard, Event, Layout, Overlay, Point, Rectangle, Shell, Size};
+use crate::{
+    Clipboard, Event, Layout, Overlay, Point, Rectangle, Shell, Size, Vector,
+};
 
 /// An [`Overlay`] container that displays multiple overlay [`overlay::Element`]
 /// children.
@@ -64,10 +66,9 @@ where
         &mut self,
         renderer: &Renderer,
         bounds: Size,
-        position: Point,
+        _position: Point,
+        translation: Vector,
     ) -> layout::Node {
-        let translation = position - Point::ORIGIN;
-
         layout::Node::with_children(
             bounds,
             self.children
diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs
index 3b69f5e6ed..acb14372f1 100644
--- a/examples/modal/src/main.rs
+++ b/examples/modal/src/main.rs
@@ -231,6 +231,7 @@ mod modal {
     use iced::mouse;
     use iced::{
         BorderRadius, Color, Element, Event, Length, Point, Rectangle, Size,
+        Vector,
     };
 
     /// A widget that centers a modal element over some base element
@@ -413,6 +414,7 @@ mod modal {
             renderer: &Renderer,
             _bounds: Size,
             position: Point,
+            _translation: Vector,
         ) -> layout::Node {
             let limits = layout::Limits::new(Size::ZERO, self.size)
                 .width(Length::Fill)
diff --git a/examples/toast/src/main.rs b/examples/toast/src/main.rs
index 5b089e8ab0..934049d5a5 100644
--- a/examples/toast/src/main.rs
+++ b/examples/toast/src/main.rs
@@ -511,6 +511,7 @@ mod toast {
             renderer: &Renderer,
             bounds: Size,
             position: Point,
+            _translation: Vector,
         ) -> layout::Node {
             let limits = layout::Limits::new(Size::ZERO, bounds)
                 .width(Length::Fill)
diff --git a/runtime/src/overlay/nested.rs b/runtime/src/overlay/nested.rs
index 062ccc7290..4256efb705 100644
--- a/runtime/src/overlay/nested.rs
+++ b/runtime/src/overlay/nested.rs
@@ -4,7 +4,9 @@ use crate::core::mouse;
 use crate::core::overlay;
 use crate::core::renderer;
 use crate::core::widget;
-use crate::core::{Clipboard, Event, Layout, Point, Rectangle, Shell, Size};
+use crate::core::{
+    Clipboard, Event, Layout, Point, Rectangle, Shell, Size, Vector,
+};
 
 /// An overlay container that displays nested overlays
 #[allow(missing_debug_implementations)]
@@ -33,19 +35,18 @@ where
         &mut self,
         renderer: &Renderer,
         bounds: Size,
-        position: Point,
+        _position: Point,
+        translation: Vector,
     ) -> layout::Node {
         fn recurse<Message, Renderer>(
             element: &mut overlay::Element<'_, Message, Renderer>,
             renderer: &Renderer,
             bounds: Size,
-            position: Point,
+            translation: Vector,
         ) -> layout::Node
         where
             Renderer: renderer::Renderer,
         {
-            let translation = position - Point::ORIGIN;
-
             let node = element.layout(renderer, bounds, translation);
 
             if let Some(mut nested) =
@@ -55,7 +56,7 @@ where
                     node.size(),
                     vec![
                         node,
-                        recurse(&mut nested, renderer, bounds, position),
+                        recurse(&mut nested, renderer, bounds, translation),
                     ],
                 )
             } else {
@@ -63,7 +64,7 @@ where
             }
         }
 
-        recurse(&mut self.overlay, renderer, bounds, position)
+        recurse(&mut self.overlay, renderer, bounds, translation)
     }
 
     /// Draws the [`Nested`] overlay using the associated `Renderer`.
diff --git a/runtime/src/user_interface.rs b/runtime/src/user_interface.rs
index dae9e0ac6c..3594ac188c 100644
--- a/runtime/src/user_interface.rs
+++ b/runtime/src/user_interface.rs
@@ -5,7 +5,9 @@ use crate::core::mouse;
 use crate::core::renderer;
 use crate::core::widget;
 use crate::core::window;
-use crate::core::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size};
+use crate::core::{
+    Clipboard, Element, Layout, Point, Rectangle, Shell, Size, Vector,
+};
 use crate::overlay;
 
 /// A set of interactive graphical elements with a specific [`Layout`].
@@ -199,7 +201,8 @@ where
             let bounds = self.bounds;
 
             let mut overlay = manual_overlay.as_mut().unwrap();
-            let mut layout = overlay.layout(renderer, bounds, Point::ORIGIN);
+            let mut layout =
+                overlay.layout(renderer, bounds, Point::ORIGIN, Vector::ZERO);
             let mut event_statuses = Vec::new();
 
             for event in events.iter().cloned() {
@@ -253,8 +256,12 @@ where
                     overlay = manual_overlay.as_mut().unwrap();
 
                     shell.revalidate_layout(|| {
-                        layout =
-                            overlay.layout(renderer, bounds, Point::ORIGIN);
+                        layout = overlay.layout(
+                            renderer,
+                            bounds,
+                            Point::ORIGIN,
+                            Vector::ZERO,
+                        );
                     });
                 }
 
@@ -448,7 +455,12 @@ where
             .map(overlay::Nested::new)
         {
             let overlay_layout = self.overlay.take().unwrap_or_else(|| {
-                overlay.layout(renderer, self.bounds, Point::ORIGIN)
+                overlay.layout(
+                    renderer,
+                    self.bounds,
+                    Point::ORIGIN,
+                    Vector::ZERO,
+                )
             });
 
             let cursor = if cursor
@@ -566,8 +578,12 @@ where
             .map(overlay::Nested::new)
         {
             if self.overlay.is_none() {
-                self.overlay =
-                    Some(overlay.layout(renderer, self.bounds, Point::ORIGIN));
+                self.overlay = Some(overlay.layout(
+                    renderer,
+                    self.bounds,
+                    Point::ORIGIN,
+                    Vector::ZERO,
+                ));
             }
 
             overlay.operate(
diff --git a/widget/src/lazy.rs b/widget/src/lazy.rs
index 589dd93807..167a055dcf 100644
--- a/widget/src/lazy.rs
+++ b/widget/src/lazy.rs
@@ -18,7 +18,7 @@ use crate::core::widget::tree::{self, Tree};
 use crate::core::widget::{self, Widget};
 use crate::core::Element;
 use crate::core::{
-    self, Clipboard, Hasher, Length, Point, Rectangle, Shell, Size,
+    self, Clipboard, Hasher, Length, Point, Rectangle, Shell, Size, Vector,
 };
 use crate::runtime::overlay::Nested;
 
@@ -333,9 +333,10 @@ where
         renderer: &Renderer,
         bounds: Size,
         position: Point,
+        translation: Vector,
     ) -> layout::Node {
         self.with_overlay_maybe(|overlay| {
-            overlay.layout(renderer, bounds, position)
+            overlay.layout(renderer, bounds, position, translation)
         })
         .unwrap_or_default()
     }
diff --git a/widget/src/lazy/component.rs b/widget/src/lazy/component.rs
index d454b72be6..ad0c382354 100644
--- a/widget/src/lazy/component.rs
+++ b/widget/src/lazy/component.rs
@@ -577,9 +577,10 @@ where
         renderer: &Renderer,
         bounds: Size,
         position: Point,
+        translation: Vector,
     ) -> layout::Node {
         self.with_overlay_maybe(|overlay| {
-            overlay.layout(renderer, bounds, position)
+            overlay.layout(renderer, bounds, position, translation)
         })
         .unwrap_or_default()
     }
diff --git a/widget/src/lazy/responsive.rs b/widget/src/lazy/responsive.rs
index ed471988b4..86d37b6c1c 100644
--- a/widget/src/lazy/responsive.rs
+++ b/widget/src/lazy/responsive.rs
@@ -6,7 +6,8 @@ use crate::core::renderer;
 use crate::core::widget;
 use crate::core::widget::tree::{self, Tree};
 use crate::core::{
-    self, Clipboard, Element, Length, Point, Rectangle, Shell, Size, Widget,
+    self, Clipboard, Element, Length, Point, Rectangle, Shell, Size, Vector,
+    Widget,
 };
 use crate::horizontal_space;
 use crate::runtime::overlay::Nested;
@@ -367,9 +368,10 @@ where
         renderer: &Renderer,
         bounds: Size,
         position: Point,
+        translation: Vector,
     ) -> layout::Node {
         self.with_overlay_maybe(|overlay| {
-            overlay.layout(renderer, bounds, position)
+            overlay.layout(renderer, bounds, position, translation)
         })
         .unwrap_or_default()
     }
diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs
index b293f9fa09..5098fa1714 100644
--- a/widget/src/overlay/menu.rs
+++ b/widget/src/overlay/menu.rs
@@ -236,6 +236,7 @@ where
         renderer: &Renderer,
         bounds: Size,
         position: Point,
+        _translation: Vector,
     ) -> layout::Node {
         let space_below = bounds.height - (position.y + self.target_height);
         let space_above = position.y;
diff --git a/widget/src/tooltip.rs b/widget/src/tooltip.rs
index b041d2e943..d5ee3de2aa 100644
--- a/widget/src/tooltip.rs
+++ b/widget/src/tooltip.rs
@@ -325,6 +325,7 @@ where
         renderer: &Renderer,
         bounds: Size,
         position: Point,
+        _translation: Vector,
     ) -> layout::Node {
         let viewport = Rectangle::with_size(bounds);