patx/afterdarklabs

update ticker: fix list paint on wider screens

Commit 51a0b3e · patx · 2026-08-25T00:03:59-04:00

Changeset
51a0b3eec4d3c8ff202a23891bc74985f9247197
Parents
6be0a40ad33c0158ad677007cc050f26a808c064

View source at this commit

Comments

No comments yet.

Log in to comment

Diff

diff --git a/docs/index.html b/docs/index.html
index 30089f9..4b5954b 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -183,7 +183,7 @@
         .hero-ticker-track {
             display: flex;
             width: max-content;
-            animation: hero-ticker-scroll 35s linear infinite;
+            animation: hero-ticker-scroll var(--ticker-duration, 35s) linear infinite;
             will-change: transform;
         }
 
@@ -229,7 +229,7 @@
         }
 
         @keyframes hero-ticker-scroll {
-            to { transform: translate3d(-50%, 0, 0); }
+            to { transform: translate3d(calc(0px - var(--ticker-distance, 50%)), 0, 0); }
         }
 
         @keyframes neon-letter-flicker {
@@ -601,6 +601,44 @@
     </footer>
 
     <script>
+        (function () {
+            const ticker = document.querySelector('.hero-ticker');
+            const track = ticker?.querySelector('.hero-ticker-track');
+            const source = track?.querySelector('.hero-ticker-group');
+            if (!ticker || !track || !source) return;
+
+            let measureFrame = 0;
+
+            function measureTicker() {
+                measureFrame = 0;
+
+                const groups = Array.from(track.querySelectorAll('.hero-ticker-group'));
+                groups.slice(1).forEach(group => group.remove());
+
+                const groupWidth = source.getBoundingClientRect().width;
+                if (!groupWidth) return;
+
+                const copiesNeeded = Math.max(2, Math.ceil(ticker.clientWidth / groupWidth) + 1);
+                for (let index = 1; index < copiesNeeded; index += 1) {
+                    const clone = source.cloneNode(true);
+                    clone.removeAttribute('aria-label');
+                    clone.setAttribute('aria-hidden', 'true');
+                    track.appendChild(clone);
+                }
+
+                track.style.setProperty('--ticker-distance', `${groupWidth}px`);
+                track.style.setProperty('--ticker-duration', `${groupWidth / 40}s`);
+            }
+
+            function scheduleTickerMeasure() {
+                if (!measureFrame) measureFrame = window.requestAnimationFrame(measureTicker);
+            }
+
+            window.addEventListener('resize', scheduleTickerMeasure);
+            document.fonts?.ready.then(scheduleTickerMeasure);
+            measureTicker();
+        })();
+
         (function () {
             const section = document.getElementById('work');
             const stage = section?.querySelector('.work-stage');