ui: Scroll stabilization
frdel committed
Jan 31, 2026 at 12:23 UTC
7cd17b6f0cb9edd156f2e2138bfede71173ac2fb
1 file changed
+45
webui/js/scroller.js
+45
@@ -17,6 +17,51 @@ export class Scroller {
17
parseFloat(getComputedStyle(document.documentElement).fontSize);
18
this.wasAtBottom = this.isAtBottom();
19
this._scrollListener = null;
20
+
21
+ this._resizeObserver = null;
22
+ this._lastClientHeight = null;
23
+
24
+ this._initScrollStabilization();
25
+ }
26
+
27
+ _initScrollStabilization() {
28
+ if (!this.element) return;
29
+
30
+ const hasStabilizationFlag =
31
+ this.element?.dataset?.scrollStabilization != null;
32
+ if (hasStabilizationFlag) return;
33
+
34
+ if (typeof ResizeObserver === "undefined") return;
35
+
36
+ this._lastClientHeight = this.element.clientHeight;
37
+ this._resizeObserver = new ResizeObserver(() => {
38
+ const prevHeight = this._lastClientHeight;
39
+ const nextHeight = this.element.clientHeight;
40
+
41
+ if (prevHeight == null) {
42
+ this._lastClientHeight = nextHeight;
43
+ return;
44
+ }
45
+
46
+ if (nextHeight === prevHeight) return;
47
+
48
+ const delta = nextHeight - prevHeight;
49
+ this._lastClientHeight = nextHeight;
50
+
51
+ if (this.wasAtBottom) {
52
+ this.scrollToBottom();
53
+ return;
54
+ }
55
+
56
+ if (delta !== 0) {
57
+ this._clearScrollingTo();
58
+ this.element.scrollTop = Math.max(0, this.element.scrollTop - delta);
59
+ }
60
+ });
61
+
62
+ this._resizeObserver.observe(this.element);
63
+
64
+ this.element.dataset.scrollStabilization = "1";
65
}
66
67
_getEffectiveScrollTop() {