diff --git a/GUI/Views/SampleDesigner/WidgetMoverButton.cpp b/GUI/Views/SampleDesigner/WidgetMoverButton.cpp
index 0ddbaf22d8e913d4a49ca1890217e445d744bd77..a3c70f7fd5ba11d9126150c5726992c0788c5a27 100644
--- a/GUI/Views/SampleDesigner/WidgetMoverButton.cpp
+++ b/GUI/Views/SampleDesigner/WidgetMoverButton.cpp
@@ -13,23 +13,42 @@
 //  ************************************************************************************************
 
 #include "GUI/Views/SampleDesigner/WidgetMoverButton.h"
+#include "Base/Utils/Assert.h"
 #include <QLayout>
 #include <QMouseEvent>
 #include <QPropertyAnimation>
+#include <QScrollArea>
+#include <QScrollBar>
 
 WidgetMoverButton::WidgetMoverButton(QWidget* parent, QWidget* widgetToMove, int ignoreOnTop)
-    : QToolButton(parent), m_widgetToMove(widgetToMove), m_ignoreOnTop(ignoreOnTop)
+    : QToolButton(parent)
+    , m_widgetToMove(widgetToMove)
+    , m_ignoreOnTop(ignoreOnTop)
+    , m_scrollArea(nullptr)
 {
     setIcon(QIcon(":/images/toolbar24dark_hambar.svg"));
+    m_dragScrollTimer.setSingleShot(false);
 }
 
 void WidgetMoverButton::mousePressEvent(QMouseEvent* event)
 {
-    m_mouseDownY = event->globalY();
+    if (m_scrollArea == nullptr) {
+        QWidget* p = parentWidget();
+        do {
+            m_scrollArea = dynamic_cast<QScrollArea*>(p);
+            p = p->parentWidget();
+        } while (p != nullptr && m_scrollArea == nullptr);
+    }
+
+    ASSERT(m_scrollArea);
+    m_globalMouseDownY = event->globalY();
+    m_hotSpot = event->globalPos()
+                - m_widgetToMove->parentWidget()->mapToGlobal(m_widgetToMove->geometry().topLeft());
 }
 
 void WidgetMoverButton::mouseReleaseEvent(QMouseEvent*)
 {
+    m_dragScrollTimer.stop();
     m_started = false;
     if (m_layoutToDeactivate != nullptr) {
         m_layoutToDeactivate->setEnabled(true);
@@ -40,7 +59,7 @@ void WidgetMoverButton::mouseReleaseEvent(QMouseEvent*)
 
 void WidgetMoverButton::mouseMoveEvent(QMouseEvent* event)
 {
-    int dy = event->globalY() - m_mouseDownY;
+    int dy = event->globalY() - m_globalMouseDownY;
     if (abs(dy) > 5 && !m_started) {
         m_started = true;
 
@@ -58,7 +77,9 @@ void WidgetMoverButton::mouseMoveEvent(QMouseEvent* event)
     if (m_started) {
 
         // -- move the dragged widget to the new position
-        m_widgetToMove->move(m_widgetToMove->x(), m_originalWidgetY + dy);
+        QPoint newPos =
+            m_widgetToMove->parentWidget()->mapFromGlobal(event->globalPos()) - m_hotSpot;
+        m_widgetToMove->move(m_widgetToMove->x(), newPos.y());
 
         // -- move other widgets to make room
         m_dropAboveThisWidget = nullptr;
@@ -99,5 +120,35 @@ void WidgetMoverButton::mouseMoveEvent(QMouseEvent* event)
 
             yTopOfLayoutItem += r.height() + m_layoutToDeactivate->spacing();
         }
+
+        // -- check whether scrolling is necessary
+        QPoint parPos = m_scrollArea->mapFromGlobal(mapToGlobal(event->pos()));
+        if (parPos.y() < 20) {
+            m_dragScrollTimer.setInterval(10);
+            m_dragScrollTimer.disconnect();
+            connect(&m_dragScrollTimer, &QTimer::timeout, [=]() { scrollParent(true); });
+            m_dragScrollTimer.start();
+        } else if (parPos.y() > m_scrollArea->height() - 20) {
+            m_dragScrollTimer.setInterval(10);
+            m_dragScrollTimer.disconnect();
+            connect(&m_dragScrollTimer, &QTimer::timeout, [=]() { scrollParent(false); });
+            m_dragScrollTimer.start();
+        } else
+            m_dragScrollTimer.stop();
     }
 }
+
+void WidgetMoverButton::scrollParent(bool up)
+{
+    auto* scrollbar = m_scrollArea->verticalScrollBar();
+    if (!scrollbar->isVisible())
+        return;
+
+    const int oldScrollValue = scrollbar->value();
+    scrollbar->setValue(oldScrollValue + (up ? -5 : 5));
+
+    // move the dragged widget to the new position to avoid jitter effects
+    // use the real change of value, not +/-5: scrolling may have been unsuccessful
+    m_widgetToMove->move(m_widgetToMove->x(),
+                         m_widgetToMove->y() + scrollbar->value() - oldScrollValue);
+}
diff --git a/GUI/Views/SampleDesigner/WidgetMoverButton.h b/GUI/Views/SampleDesigner/WidgetMoverButton.h
index 1f0e29002c1e943b97f4ffe8f4898b936dffd37f..95ecfc29c25c25e0a7f9ed67aaa6415334af40cf 100644
--- a/GUI/Views/SampleDesigner/WidgetMoverButton.h
+++ b/GUI/Views/SampleDesigner/WidgetMoverButton.h
@@ -15,8 +15,11 @@
 #ifndef BORNAGAIN_GUI_VIEWS_SAMPLEDESIGNER_WIDGETMOVERBUTTON_H
 #define BORNAGAIN_GUI_VIEWS_SAMPLEDESIGNER_WIDGETMOVERBUTTON_H
 
+#include <QTimer>
 #include <QToolButton>
 
+class QScrollArea;
+
 //! Button to move a widget vertically in a layout.
 //!
 //! With this button, the "move layer" feature in the layer oriented sample editor is realized
@@ -47,15 +50,21 @@ signals:
     void startingToMove();
     void finishedMoving(QWidget* widgetToMove, QWidget* moveAboveThisWidget);
 
+private:
+    void scrollParent(bool up);
+
 private:
     bool m_started = false;
-    int m_mouseDownY;
+    int m_globalMouseDownY;
     QLayout* m_layoutToDeactivate = nullptr;
     QWidget* m_widgetToMove;
     QWidget* m_dropAboveThisWidget;
     int m_originalWidgetY;
     int m_yOfFirstRelevantWidget;
     int m_ignoreOnTop;
+    QTimer m_dragScrollTimer;
+    QScrollArea* m_scrollArea;
+    QPoint m_hotSpot; //!< The mouse-down coordinates in the widget to move
 };