@@ -1700,7 +1700,7 @@ async function navigate({
1700
1700
await tick ( ) ;
1701
1701
1702
1702
// we reset scroll before dealing with focus, to avoid a flash of unscrolled content
1703
- const scroll = popped ? popped . scroll : noscroll ? scroll_state ( ) : null ;
1703
+ let scroll = popped ? popped . scroll : noscroll ? scroll_state ( ) : null ;
1704
1704
1705
1705
if ( autoscroll ) {
1706
1706
const deep_linked = url . hash && document . getElementById ( get_id ( url ) ) ;
@@ -1711,6 +1711,15 @@ async function navigate({
1711
1711
// because it natively supports the `scroll-margin` and `scroll-behavior`
1712
1712
// CSS properties.
1713
1713
deep_linked . scrollIntoView ( ) ;
1714
+
1715
+ // Get target position at this point because with smooth scrolling the scroll position
1716
+ // retrieved from current x/y above might be wrong (since we might not have arrived at the destination yet)
1717
+ const { top, left } = deep_linked . getBoundingClientRect ( ) ;
1718
+
1719
+ scroll = {
1720
+ x : pageXOffset + left ,
1721
+ y : pageYOffset + top
1722
+ } ;
1714
1723
} else {
1715
1724
scrollTo ( 0 , 0 ) ;
1716
1725
}
@@ -1724,7 +1733,7 @@ async function navigate({
1724
1733
document . activeElement !== document . body ;
1725
1734
1726
1735
if ( ! keepfocus && ! changed_focus ) {
1727
- reset_focus ( url ) ;
1736
+ reset_focus ( url , scroll ) ;
1728
1737
}
1729
1738
1730
1739
autoscroll = true ;
@@ -2464,7 +2473,7 @@ function _start_router() {
2464
2473
// /#top and click on a link that goes to /#top. In those cases just go to
2465
2474
// the top of the page, and avoid a history change.
2466
2475
if ( hash === '' || ( hash === 'top' && a . ownerDocument . getElementById ( 'top' ) === null ) ) {
2467
- window . scrollTo ( { top : 0 } ) ;
2476
+ scrollTo ( { top : 0 } ) ;
2468
2477
} else {
2469
2478
const element = a . ownerDocument . getElementById ( decodeURIComponent ( hash ) ) ;
2470
2479
if ( element ) {
@@ -2923,8 +2932,9 @@ let resetting_focus = false;
2923
2932
2924
2933
/**
2925
2934
* @param {URL } url
2935
+ * @param {{ x: number, y: number } | null } scroll
2926
2936
*/
2927
- function reset_focus ( url ) {
2937
+ function reset_focus ( url , scroll = null ) {
2928
2938
const autofocus = document . querySelector ( '[autofocus]' ) ;
2929
2939
if ( autofocus ) {
2930
2940
// @ts -ignore
@@ -2936,7 +2946,7 @@ function reset_focus(url) {
2936
2946
// starting point to the fragment identifier.
2937
2947
const id = get_id ( url ) ;
2938
2948
if ( id && document . getElementById ( id ) ) {
2939
- const { x, y } = scroll_state ( ) ;
2949
+ const { x, y } = scroll ?? scroll_state ( ) ;
2940
2950
2941
2951
// `element.focus()` doesn't work on Safari and Firefox Ubuntu so we need
2942
2952
// to use this hack with `location.replace()` instead.
0 commit comments