patx/voldservices
fix scroll
Commit b03d641 · patx · 2026-08-19T00:58:21-04:00
Comments
No comments yet.
Diff
diff --git a/docs/index.html b/docs/index.html
index 4432000..538fb74 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1442,14 +1442,13 @@
<img class="hero-fallback" src="https://voldservices.com/img/hero-scrub-poster.jpg" alt="" aria-hidden="true" />
<video
id="hero-video"
+ data-desktop-src="/hero-scrub.mp4"
+ data-mobile-src="/hero-scrub-mobile.mp4"
poster="https://voldservices.com/img/hero-scrub-poster.jpg"
muted playsinline webkit-playsinline preload="auto"
controlslist="nodownload nofullscreen noremoteplayback"
disablepictureinpicture disableremoteplayback
- aria-hidden="true" tabindex="-1">
- <source media="(max-width: 720px)" src="https://voldservices.com/hero-scrub-mobile.mp4" type="video/mp4" />
- <source src="https://voldservices.com/hero-scrub.mp4" type="video/mp4" />
- </video>
+ aria-hidden="true" tabindex="-1"></video>
</div>
<div class="hero-grain" aria-hidden="true"></div>
@@ -2140,6 +2139,7 @@
var heroVideoVisible = false;
var heroVideoRevealPending = false;
var heroVideoProgress = 0;
+ var heroVideoObjectUrl = '';
function clamp01(value) {
return Math.max(0, Math.min(1, value));
@@ -2238,6 +2238,41 @@
if (!heroUsesTouch || heroTouchStarted) primeHeroVideo();
}
+ function attachHeroVideoSource(source) {
+ heroVideo.src = source;
+ heroVideo.load();
+ }
+
+ /* The origin currently serves MP4 files without byte-range responses.
+ Mobile's smaller encode can finish downloading before that becomes
+ noticeable, but desktop seeks otherwise snap back to frame zero.
+ Buffer the desktop file into a blob so its full timeline is locally
+ seekable, keeping the poster visible until the first frame is ready. */
+ function loadHeroVideo() {
+ var mobileSource = window.innerWidth <= 720;
+ var source = mobileSource
+ ? heroVideo.getAttribute('data-mobile-src')
+ : heroVideo.getAttribute('data-desktop-src');
+
+ if (mobileSource || typeof window.fetch !== 'function' || typeof window.URL.createObjectURL !== 'function') {
+ attachHeroVideoSource(source);
+ return;
+ }
+
+ window.fetch(source, { cache: 'force-cache' })
+ .then(function (response) {
+ if (!response.ok) throw new Error('Hero video request failed');
+ return response.blob();
+ })
+ .then(function (blob) {
+ heroVideoObjectUrl = window.URL.createObjectURL(blob);
+ attachHeroVideoSource(heroVideoObjectUrl);
+ })
+ .catch(function () {
+ attachHeroVideoSource(source);
+ });
+ }
+
if (reduceMotion) {
heroVideo.pause();
} else {
@@ -2248,8 +2283,14 @@
// Cached media can reach metadata before this bottom-of-page script runs.
if (heroVideo.readyState >= 1) prepareHeroVideo();
+
+ loadHeroVideo();
}
+ window.addEventListener('beforeunload', function () {
+ if (heroVideoObjectUrl) window.URL.revokeObjectURL(heroVideoObjectUrl);
+ });
+
// If the user scrolls again while a seek is being decoded, catch the
// playhead up to the most recent position as soon as that frame lands.
heroVideo.addEventListener('seeked', function () {