diff -NarU2 easymde-mod1/src/js/easymde.js easymde-edit/src/js/easymde.js
--- easymde-mod1/src/js/easymde.js	2020-05-01 14:34:19.878774400 +0200
+++ easymde-edit/src/js/easymde.js	2020-05-01 21:24:44.142611200 +0200
@@ -2189,4 +2189,5 @@
 };
 
+
 EasyMDE.prototype.createSideBySide = function () {
     var cm = this.codemirror;
@@ -2223,12 +2224,80 @@
         }
         pScroll = true;
-        var height = v.getScrollInfo().height - v.getScrollInfo().clientHeight;
-        var ratio = parseFloat(v.getScrollInfo().top) / height;
-        var move = (preview.scrollHeight - preview.clientHeight) * ratio;
-        preview.scrollTop = move;
+        var md_vp = v.getScrollInfo();
+        // viewport top: top
+        // viewport size: clientHeight
+        // document size: height
+        var md_scroll_y = md_vp.top + md_vp.clientHeight / 2;
+        var md_center_n = cm.lineAtHeight(md_scroll_y, 'local') + 1;
+        var md_next_n = md_center_n;
+        var md_top = cm.heightAtLine(md_center_n - 1, 'local');
+        while (md_next_n < cm.lineCount())
+            if (cm.getLine(md_next_n++).replace(/\s+/g, '').length > 0)
+                break;
+        var md_end = cm.heightAtLine(md_next_n - 1, 'local');
+        var md_frac = (md_scroll_y - md_top) * 1.0 / (md_end - md_top);
+        var get_pre_line = function(line_n, increase) {
+            var end = 0;
+            var step = -1;
+            if (increase) {
+                step = 1;
+                end = line_n + 1000;
+            }
+            // there might be multiple elements in the marked.js output,
+            // take the element with the biggest height
+            var biggest = -1;
+            var line_dom = null;
+            for (; line_n != end; line_n += step) {
+                var hits = document.querySelectorAll('.editor-preview-side *[data-ln=\'' + line_n + '\']');
+                for (var i = 0; i < hits.length; i++) {
+                    var hit_size = hits[i].offsetHeight;
+                    if (biggest < hit_size) {
+                        biggest = hit_size;
+                        line_dom = hits[i];
+                    }
+                }
+                if (line_dom) {
+                    var ret_y = 0;
+                    var el = line_dom;
+                    while (el && (el.getAttribute('class') + '').indexOf('editor-preview-side') < 0) {
+                        ret_y += el.offsetTop;
+                        el = el.offsetParent;
+                    }
+                    return [line_n, line_dom, ret_y];
+                }
+            }
+            return null;
+        };
+        var pre1 = get_pre_line(md_center_n, false);
+        var pre2 = get_pre_line(pre1[0] + 1, true) ||
+            [cm.lineCount(), null, preview.scrollHeight];
+        
+        //console.log('code-center %d, frac %.2f, pre [%d,%d] [%d,%d]',
+        //    md_center_n, md_frac, pre1[0], pre1[2], pre2[0], pre2[2]);
+        
+        // [0] is the markdown line which matches that preview y-pos
+        // and since not all preview lines are tagged with a line-number
+        // take the lineno diff and divide it by the distance
+        var pre_frac = md_frac / ((pre2[0] - pre1[0]) / (md_next_n - md_center_n));
+
+        // then use that fraction for the scroll offset
+        var pre_y = pre1[2] + (pre2[2] - pre1[2]) * pre_frac;
+
+        // unless we couldn't match the markdown line exactly to any preview line
+        if (md_center_n > pre1[0] && md_center_n < pre2[0])
+            pre_y = pre2[2];
+
+        // except jump to the top or bottom if we're close enough
+        if (md_vp.top < 32)
+            pre_y = 0;
+        else if (md_vp.top + 32 >= md_vp.height - md_vp.clientHeight)
+            pre_y = preview.scrollHeight;
+
+        preview.scrollTop = pre_y - preview.clientHeight / 2;
     });
 
     // Syncs scroll  preview -> editor
-    preview.onscroll = function () {
+    // disabled since it should be possible to intentionally unsync
+    preview.onscroll_fgsfds = function () {
         if (pScroll) {
             pScroll = false;
