diff --git a/src/display/operations.js b/src/display/operations.js
index 15a041c6ab3167f2e622b25a23b6c20cb17572c9..6748af43e3a09eebb3941b55beeea5edcc35acf6 100644
--- a/src/display/operations.js
+++ b/src/display/operations.js
@@ -140,7 +140,7 @@ function endOperation_finish(op) {
     display.wheelStartX = display.wheelStartY = null
 
   // Propagate the scroll position to the actual DOM scroller
-  if (op.scrollTop != null) setScrollTop(cm, op.scrollTop, true)
+  if (op.scrollTop != null) setScrollTop(cm, op.scrollTop, op.forceScroll)
 
   if (op.scrollLeft != null) setScrollLeft(cm, op.scrollLeft, true, true)
   // If we need to scroll a specific position into view, do so.
diff --git a/src/display/scrolling.js b/src/display/scrolling.js
index be1a4e00a98b42090c877b5824ac981e5fa8669e..96192cab9b8383f0c06ca5f38b4b3636bed931f8 100644
--- a/src/display/scrolling.js
+++ b/src/display/scrolling.js
@@ -156,16 +156,17 @@ export function scrollToCoordsRange(cm, from, to, margin) {
 export function updateScrollTop(cm, val) {
   if (Math.abs(cm.doc.scrollTop - val) < 2) return
   if (!gecko) updateDisplaySimple(cm, {top: val})
-  setScrollTop(cm, val)
+  setScrollTop(cm, val, true)
   if (gecko) updateDisplaySimple(cm)
   startWorker(cm, 100)
 }
+
 export function setScrollTop(cm, val, forceScroll) {
   val = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val)
   if (cm.display.scroller.scrollTop == val && !forceScroll) return
   cm.doc.scrollTop = val
   cm.display.scrollbars.setScrollTop(val)
-  cm.display.scroller.scrollTop = val
+  if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val
 }
 
 // Sync scroller and scrollbar, ensure the gutter elements are