Skip to content

Commit 110a5a8

Browse files
authored
fix: robustify bind:scrollX/Y binding (#11655)
- we were scrolling to the given value, which we shouldn't for accessibility reasons (Svelte 4 didn't do it either) - we need to notify of the value 0 if there's no scroll (#11623 (comment))
1 parent d288735 commit 110a5a8

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

.changeset/popular-roses-teach.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
fix: robustify `bind:scrollX/Y` binding

packages/svelte/src/internal/client/dom/elements/bindings/window.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { render_effect } from '../../../reactivity/effects.js';
1+
import { effect, render_effect } from '../../../reactivity/effects.js';
22
import { listen } from './shared.js';
33

44
/**
@@ -22,18 +22,21 @@ export function bind_window_scroll(type, get_value, update) {
2222
passive: true
2323
});
2424

25-
var latest_value = 0;
2625
var scrolling = false;
2726

2827
/** @type {ReturnType<typeof setTimeout>} */
2928
var timeout;
3029
var clear = () => {
3130
scrolling = false;
3231
};
32+
var first = true;
3333

3434
render_effect(() => {
35-
latest_value = get_value();
36-
if (!scrolling && latest_value != null) {
35+
var latest_value = get_value();
36+
// Don't scroll to the initial value for accessibility reasons
37+
if (first) {
38+
first = false;
39+
} else if (!scrolling && latest_value != null) {
3740
scrolling = true;
3841
clearTimeout(timeout);
3942
if (is_scrolling_x) {
@@ -45,6 +48,15 @@ export function bind_window_scroll(type, get_value, update) {
4548
}
4649
});
4750

51+
// Browsers fire the scroll event only if the scroll position is not 0.
52+
// This effect is (almost) guaranteed to run after the scroll event would've fired.
53+
effect(() => {
54+
var value = window[is_scrolling_x ? 'scrollX' : 'scrollY'];
55+
if (value === 0) {
56+
update(value);
57+
}
58+
});
59+
4860
render_effect(() => {
4961
return () => {
5062
removeEventListener('scroll', target_handler);

0 commit comments

Comments
 (0)