From 059ee1744e25cc7bb842c8425c6b7cfb0a30b392 Mon Sep 17 00:00:00 2001 From: screentinker Date: Thu, 16 Jul 2026 14:11:21 -0500 Subject: [PATCH] =?UTF-8?q?fix(widgets):=20directory=20board=20scroll=20st?= =?UTF-8?q?utter=20=E2=80=94=20seamless=20loop=20gap=20mismatch=20(#197)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vertical auto-scroll is a CSS keyframe that translates the track by cycleH = baseH + GAP_PX and loops linear infinite. GAP_PX was 100 but the actual .gap element between the content and its seamless clone is 120px, so every cycle the reset landed 20px off — a visible jump/stutter once per loop. Set GAP_PX = 120 to match the .gap CSS, and drive each gap element's height from GAP_PX inline so the scroll math and the rendered gap can never drift again. Co-authored-by: Claude Opus 4.8 --- server/routes/widgets.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/routes/widgets.js b/server/routes/widgets.js index 1e0d20d..67e8cab 100644 --- a/server/routes/widgets.js +++ b/server/routes/widgets.js @@ -512,7 +512,8 @@ function renderDirectoryBoard(c) { var SPEEDS = { slow: 20, medium: 45, fast: 75 }; if (cfg.theme === 'light') document.body.classList.add('light'); - var GAP_PX = 100; + var GAP_PX = 120; // MUST match the .gap element height (set inline below) — the scroll loop + // translates by baseH+GAP_PX, so any mismatch jumps that many px each cycle. var MIN_SCROLL_PX_SEC = 5; // anti-burn-in minimum when content fits // ----- header ----- @@ -629,7 +630,8 @@ function renderDirectoryBoard(c) { while (track.children.length > 1) track.removeChild(track.lastChild); var gap = document.createElement('div'); gap.className = 'gap'; - track.appendChild(gap); + gap.style.height = GAP_PX + 'px'; // MUST equal GAP_PX — the loop translates by baseH+GAP_PX; + track.appendChild(gap); // a mismatch (was CSS 120 vs GAP_PX 100) jumps 20px each cycle. var baseH = baseBlock.getBoundingClientRect().height; var cycleH = baseH + GAP_PX; // distance to translate per loop @@ -643,6 +645,7 @@ function renderDirectoryBoard(c) { if (i < cloneCount - 1) { var g = document.createElement('div'); g.className = 'gap'; + g.style.height = GAP_PX + 'px'; // keep every clone-gap == GAP_PX (seamless loop) track.appendChild(g); } }