YES canvas: size off its own container rect, not window.innerHeight
Deploy / deploy (push) Successful in 34s

setupCanvas() measured window.innerWidth/innerHeight directly, then a
resize listener gated on innerWidth changing (guessing which resize
events were "real" vs mobile Safari's address-bar animation). That
measurement had nothing to do with .hero-yes's actual CSS height, so
the canvas and its box could end up disagreeing - which is what was
producing the observed jump in content below the hero on scroll, not
the choice of viewport unit on its own.

Switched to ResizeObserver on .hero-canvas (which tracks .hero-yes via
inset:0), using its contentRect directly. This also drops the
innerWidth-gating heuristic entirely: a fixed-height box never fires
a ResizeObserver callback during the toolbar animation in the first
place, so there's nothing to gate.

Also updated the mouse/touch position normalization to use the
canvas's own displayWidth/displayHeight instead of
window.innerWidth/innerHeight, for the same reason - and fixed the
.hero-yes comment, which still described the lvh reasoning from a
prior attempt after the height value itself had been changed back to
svh directly on origin/main.
This commit is contained in:
Bendik Aagaard Lynghaug
2026-08-06 21:22:00 +02:00
parent cc5174813c
commit d7f280e681
2 changed files with 41 additions and 31 deletions
+11 -11
View File
@@ -153,17 +153,17 @@ main.loading, main.not-found {
position: relative;
max-width: none;
width: 100%;
/* lvh (large viewport height), not svh: svh pins to the *smallest*
viewport (toolbar visible), which never grows once the browser
auto-collapses its toolbar on the first scroll - so the actual
visible screen becomes taller than this box, and the content
below appears to snap into the newly-revealed space the moment
that happens. lvh pins to the toolbar-collapsed size instead,
matching the settled state scrolling actually lands on, so
there's no gap to reveal. (svh is the right choice for the
opposite case - a fixed element that must never be hidden behind
the toolbar - not a hero at the top of a scrolling page.)
Plain-vh fallback declared first - an engine without lvh support
/* svh (small viewport height): a fixed, stable length - computed
once, never recalculated mid-scroll as mobile Safari's address
bar hides/shows, unlike plain vh/dvh on some engines. Pinned to
the *smallest* possible viewport (toolbar visible) so the box
never needs to grow into space the toolbar might reclaim.
yes.js's canvas measures this box's own rendered rect (not
window.innerWidth/innerHeight) via ResizeObserver, so the canvas
always matches whatever height this resolves to - the two can't
disagree, which is what was actually causing the content below to
visibly jump.
Plain-vh fallback declared first - an engine without svh support
ignores the invalid second line rather than falling through to
auto height, which would collapse this to the height of its
in-flow content and clip the canvas via overflow:hidden below. */