fix(parallax): drive --parallax-pos via CSS scroll animation to kill SSR/hydration position pop

This commit is contained in:
daniel-c-harvey
2026-06-11 11:57:43 -04:00
parent 16f356a760
commit 91566692f6
2 changed files with 59 additions and 4 deletions
@@ -1,3 +1,9 @@
@property --parallax-pos {
syntax: '<percentage>';
inherits: true;
initial-value: 0%;
}
.parallax-window {
position: relative;
overflow: hidden;
@@ -37,6 +43,39 @@
opacity: 1;
}
/*
* Cascade interaction for --parallax-pos:
*
* Before WASM (SSR / hydration):
* @property initial-value: 0%
* → CSS animation (view timeline) overrides → correct position from scroll
*
* After WASM (JS running):
* JS element.style.setProperty('--parallax-pos', ...) [inline style]
* → inline style beats animation → JS takes over seamlessly
*
* prefers-reduced-motion:
* animation: none → @property initial-value 0% used → static image
* JS also skips scroll listener
*/
@supports (animation-timeline: view()) {
@keyframes parallax-pan {
from { --parallax-pos: var(--parallax-from, 0%); }
to { --parallax-pos: var(--parallax-to, 0%); }
}
.parallax-window {
animation: parallax-pan linear both;
animation-timeline: view();
}
@media (prefers-reduced-motion: reduce) {
.parallax-window {
animation: none;
}
}
}
@media (prefers-reduced-motion: reduce) {
.parallax-window {
--parallax-pos: 0%;