Skip to content

Commit 263f875

Browse files
committed
@ Banner: drop column morph + .enter to stop SPA-nav glitches
Two related glitches when navigating between / and a sketch: - "Page slides down dramatically + fades" on outbound nav from a pinned state. Cause: <section class="column" transition:name="column"> made the browser morph column's bbox between OLD and NEW pages during view transition. With pinned sticky descendants, OLD column is much taller (banner at e.g. 21% relative offset); NEW sketch column is ~1500px, scaling that 21% lands the banner at viewport y≈315 — a ~250px drop during the morph, with h1 and list items getting the same treatment. Amplitude tracked scroll position because higher scroll = higher relative offset in OLD column. Removing the name leaves the column under Astro's generic page fade; nothing repositions. Stage keeps its name (canvas needs to persist across nav). - Banner sometimes invisible after SPA nav back from a sketch. The banner-wrap had .enter class which sets opacity: 0 in its initial keyframe with animation-fill-mode: both. If the animation timeline paused / stalled (view transitions can suspend it), the banner was stranded at opacity 0 even though init() runs synchronously to remove the class — there was a race window. Dropping .enter from the markup entirely removes the race; h1 / .sub / list items still get their staggered reveal on first load. Also gave banner-wrap its own transition:name="banner" as a belt- and-braces — even if column ever gets a name back, banner now has an independent pseudo anchored to its own bbox.
1 parent dee17f6 commit 263f875

2 files changed

Lines changed: 36 additions & 2 deletions

File tree

src/layouts/BaseLayout.astro

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,19 @@ const ogImage = image ? new URL(image, Astro.site).toString() : undefined;
5959
<slot name="stage" />
6060
<span class="stage-pause" aria-hidden="true">paused</span>
6161
</aside>
62-
<section class="column" transition:name="column">
62+
{/* No transition:name on column. With it, the browser morphs
63+
the column's bbox between OLD and NEW pages — and when the
64+
user is scrolled with sticky elements pinned (banner, header)
65+
the OLD bbox is much taller than NEW (sketch pages have less
66+
content), so during the morph every descendant is repositioned
67+
by relative offset (e.g. a banner pinned at scrollY=1000 sits
68+
at ~21% of the OLD column; scaled into a 1500px NEW column it
69+
lands at viewport y=315 — dropping ~250px during nav). h1 and
70+
list items get the same treatment. Without the name, the
71+
column just fades as a generic page-level transition; nothing
72+
repositions. Stage keeps its name because the canvas needs to
73+
persist its render across navigation. */}
74+
<section class="column">
6375
<slot />
6476
</section>
6577
</main>

src/pages/index.astro

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,29 @@ const BANNER_H = 120;
6262
<p class="sub enter" style="--i: 1;">SUNKEN KEEP / 保持沉没</p>
6363
</header>
6464

65-
<div class="banner-wrap enter" style={`--i: 2; --banner-h: ${BANNER_H}px;`}>
65+
{/* No `.enter` class on the banner-wrap. The fade-in is purely
66+
cosmetic and its `animation-fill-mode: both` initial frame
67+
(opacity: 0) can strand the banner invisible if the timeline
68+
ever gets paused or stalls — view transitions on SPA nav back
69+
from a sketch can do that intermittently, even after init's
70+
classList.remove('enter') would normally fire. Skipping the
71+
animation entirely on the banner removes the race; h1 / .sub /
72+
list items still get their .enter staggered reveal.
73+
74+
transition:name lifts the banner out of the column's view
75+
transition. The column has its own name and morphs between
76+
OLD/NEW bboxes — when scrolled, OLD column is much taller than
77+
NEW (sketch pages have less content), so its descendants get
78+
positioned by *relative offset* during the morph. A pinned
79+
banner at scrollY=1000 lives at ~21% down the OLD column;
80+
scaled into NEW's ~1500px column it lands at viewport y=315 —
81+
the "big downward drop + fade" the user saw on nav. With its
82+
own transition name the banner gets an independent pseudo
83+
anchored to its current bbox, so it just fades from where it
84+
sits. The further scrolled (= higher % in OLD column), the
85+
bigger the drop without this — explains why amplitude tracks
86+
scroll position. */}
87+
<div class="banner-wrap" style={`--banner-h: ${BANNER_H}px;`} transition:name="banner">
6688
<CineBanner
6789
sources={["/banner/lobby/lamp.mp4"]}
6890
height={BANNER_H}

0 commit comments

Comments
 (0)