Search code examples
javascriptmacossafari

Prevent Safari from automatically scrolling to focused element (scrollback technique stopped working in Safari 12)


Safari for desktop automatically scrolls the page to any input element that I focus from javascript. This behavior can be seen right here:

https://codepen.io/anon/pen/JmKPwZ

I have found no way to prevent this automatic scrolling. However, there is a known workaround - save the screen position first and scroll back to that position after focusing:

var el = document.getElementById("editable");
var x = window.scrollX, y = window.scrollY; // save position
el.focus();
// manipulate selection inside the focused element with `document.createRange()`
// and do other stuff
window.scrollTo(x, y); // restore position

This workaround used to work fine in Safari 10 and stopped working in Safari 12. Calling scrollTo after focusing doesn't do anything anymore. However, if scrollTo is executed with a delay (even a really short one), everything works:

var el = document.getElementById("editable");
var x = window.scrollX, y = window.scrollY; // save position
el.focus();
// manipulate selection inside the focused element with `document.createRange()`
// and do other stuff
setTimeout(function() {
    window.scrollTo(x, y); // restore position
}, 1);

But with this 1-millisecond delay one can see the page first scrolls to the input field and then very quickly back to the original position, so the new workaround is far from perfect.

Is there any way to gracefully prevent desktop Safari from scrolling the page to focused element automatically or at least a good workaround to mitigate that behavior?


Solution

  • After much poking around I've stumbled upon a solution that works:

    var el = document.getElementById("editable");
    var scrollTop = document.body.scrollTop; // save position
    el.focus();
    // manipulate selection inside the focused element with `document.createRange()`
    // and do other stuff
    document.body.scrollTop = scrollTop;
    

    For some reason saving document.body.scrollTop works, while saving window.scrollX and window.scrollY doesn't.