diff options
| author | user <user@clank> | 2026-08-30 15:43:42 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-30 15:43:42 +0200 |
| commit | 37f79de1f52c67fa99af8da8f9f96f5f26604ffb (patch) | |
| tree | e27d1d83ba4d6b6bf48c87fa38fc9a0a71cb9f5a | |
| parent | webdemo: fit with font size, not scale -- a transform misplaces clicks (diff) | |
| download | slosh-37f79de1f52c67fa99af8da8f9f96f5f26604ffb.tar.gz slosh-37f79de1f52c67fa99af8da8f9f96f5f26604ffb.tar.xz slosh-37f79de1f52c67fa99af8da8f9f96f5f26604ffb.zip | |
web: centre the floating logo in the air above the terminal
A fixed top worked at one viewport height and overlapped the pinned
terminal at others: the terminal's top edge is (viewport - the stage's
lift padding) / 2 - half the player, which no constant tracks. Measure
it instead, centre the logo in what remains, and hide it outright when
a short viewport leaves no air -- hiding beats overlapping.
Re-placed on resize and by a ResizeObserver on the player mounts, not
on the pin: the players are zero-height until their casts arrive, and
the pin is a 100vh box that never resizes, so watching it would freeze
the placement at the pre-load height.
| -rw-r--r-- | web/index.html | 24 | ||||
| -rw-r--r-- | web/site.css | 3 |
2 files changed, 27 insertions, 0 deletions
diff --git a/web/index.html b/web/index.html index f491f24..db43867 100644 --- a/web/index.html +++ b/web/index.html @@ -297,6 +297,30 @@ if (bigLogo && littleLogo && "IntersectionObserver" in window) { }).observe(bigLogo); } +// ...and vertically centred in the air between the viewport top and the +// pinned terminal's top edge. That edge is (viewport - the stage's lift +// padding) / 2 - half the player, which moves with both the window and the +// player's own height -- so it is measured, not guessed in CSS. Hidden when +// the air runs out rather than allowed to overlap the terminal. +const stagePin = document.querySelector(".stage-pin"); +function placeLittleLogo() { + const player = stagePin && stagePin.querySelector(".stage-active"); + if (!player || !littleLogo) return; + const pad = parseFloat(getComputedStyle(stagePin).paddingBottom) || 0; + const termTop = (innerHeight - pad) / 2 - player.offsetHeight / 2; + const air = termTop - littleLogo.offsetHeight; + littleLogo.style.top = Math.max(8, air / 2) + "px"; + littleLogo.style.visibility = air >= 16 ? "" : "hidden"; +} +if (stagePin && littleLogo) { + placeLittleLogo(); + window.addEventListener("resize", placeLittleLogo); + // The players size themselves when their casts arrive -- and the pin is a + // 100vh box that never resizes, so watch the players, not the pin. + const ro = new ResizeObserver(placeLittleLogo); + for (const el of stagePin.querySelectorAll("[data-sloshcast]")) ro.observe(el); +} + // The install box opens on the platform reading it; the tabs are CSS. const ua = navigator.userAgent; const os = /Windows/i.test(ua) ? "windows" : /Mac/i.test(ua) ? "macos" : "linux"; diff --git a/web/site.css b/web/site.css index a5b28c4..d9764f9 100644 --- a/web/site.css +++ b/web/site.css @@ -57,6 +57,9 @@ kbd { .logo-float { position: fixed; + /* The resting value only: the script centres it in the air between the + * viewport top and the pinned terminal's top edge, which no fixed number + * tracks across viewport heights. */ top: 13.8rem; /* Centred on the stage column: the tour is layout-centred and the stage * is the 3fr of its 3fr/2fr split, so the terminal's midline sits at |
