Merge nucleic/upbeat-jade-ibis-kt5e into main
Mirrored from corpo f8f4b82.
This commit is contained in:
+73
-25
@@ -15,10 +15,12 @@ const canonical = new URL('/', Astro.site);
|
||||
hand those 120px to the page, so no element and no viewport unit reaches them —
|
||||
see the note on .ambient for what actually resolves it. -->
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<!-- Not --paper. Safari paints its overscroll regions with this flat colour, but
|
||||
the page underneath is the ambient field, which lifts the edges well off paper.
|
||||
Measured off rendered pixels at the top and bottom edges. -->
|
||||
<meta name="theme-color" content="#0f1813" />
|
||||
<!-- --paper, and it has to stay --paper: this is one of the surfaces Safari fills
|
||||
around the page, alongside the canvas, and the field is now brought to --paper
|
||||
at the viewport edges so all of them agree. A "better matching" value here is
|
||||
precisely the bug — it reintroduces a colour that differs from the page edge,
|
||||
which surfaces as a bar whenever Safari switches to it during a scroll. -->
|
||||
<meta name="theme-color" content="#0a100c" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
@@ -175,10 +177,10 @@ const canonical = new URL('/', Astro.site);
|
||||
right: 0;
|
||||
left: 0;
|
||||
/* Deliberately not inset: 0. A fixed box pinned to the bottom stops at the small
|
||||
viewport, but iOS Safari keeps rendering the page behind its translucent
|
||||
toolbar — so the strip between svh and lvh fell back to flat paper and read as
|
||||
a grey bar under the chrome. Sized to the large viewport, the field paints
|
||||
through the toolbar instead. */
|
||||
viewport, leaving the strip between svh and lvh unpainted by this layer — which
|
||||
matters because the toolbar retracts and hands those pixels back to the page.
|
||||
Sized to the large viewport, the layer owns them in both states; what it puts
|
||||
there is the ::after note's business. */
|
||||
height: 100%;
|
||||
height: 100lvh;
|
||||
overflow: hidden;
|
||||
@@ -194,23 +196,55 @@ const canonical = new URL('/', Astro.site);
|
||||
and no viewport-fit=cover reaches them; earlier attempts only moved the seam.
|
||||
|
||||
So the canvas is the single point, and there is exactly one thing to get right:
|
||||
the canvas colour and the page's own edge colour have to be equal. The canvas can
|
||||
only be flat --paper, and the field is a moving light whose edge tone drifts, so
|
||||
matching by picking a constant is a value that is wrong again as soon as the bands
|
||||
move. Instead the field is brought to zero at the bottom of the viewport — then
|
||||
page edge, canvas and theme-color are all --paper by construction, whatever the
|
||||
animation is doing, and the seam cannot come back.
|
||||
every surface Safari fills around the page, and the page's own colour where it
|
||||
meets them, must be the same paint. Those surfaces can only be flat colours, and
|
||||
the field is a moving light whose edge tone drifts, so matching them by picking a
|
||||
constant is a value that is wrong again as soon as the bands move — and wrong in a
|
||||
different way in each scroll state, which is what made the bar come and go.
|
||||
|
||||
Costs nothing to look at: this falls inside the strip Safari's toolbar already
|
||||
covers. Static, so the layer still composites without repainting per frame. */
|
||||
The field is therefore brought to zero at both edges of the viewport. --paper is
|
||||
then the only colour in play: canvas, theme-color, overscroll, the chrome strips,
|
||||
and the page itself where it touches any of them. There is no second value left
|
||||
for Safari to swap in, so no scroll state, toolbar collapse or fixed-layer
|
||||
reposition has anything to expose. That is the property to preserve — if this ever
|
||||
needs editing, keep the edges at --paper rather than tuning a colour to match.
|
||||
|
||||
The one thing that has to be right is where the bottom reaches --paper, and it is
|
||||
not a number to taste. This layer is fixed and 100lvh tall, but the bottom edge of
|
||||
what the reader can see is only at 100lvh with the toolbar collapsed; expanded, it
|
||||
is at 100svh, ~100px higher, and Safari slides between the two mid-scroll. Ending
|
||||
the fade at the element's own bottom therefore left the visible edge sitting part
|
||||
way up the fade whenever the toolbar was out — lighter than the strip below it, so
|
||||
the bar came back — and clean again once the toolbar went away. A boundary at a
|
||||
coordinate that moves is not a fix, it is the same bug relocated.
|
||||
|
||||
Nor can that band simply be held flat: those pixels are behind the chrome in one
|
||||
state and are ordinary page in the other, so a flat patch there is invisible with
|
||||
the toolbar out and a hard-edged band the moment it retracts. Both failures are
|
||||
the same failure — an edge existing anywhere the viewport boundary can land.
|
||||
|
||||
So there is no edge. The field decays to --paper continuously, and is already
|
||||
exactly --paper by 100svh, above the highest position the visible bottom can take;
|
||||
everything from there to 100lvh is the same paint. Every boundary the viewport
|
||||
could land on is gone, in either state and part way through the transition between
|
||||
them. The decay is spread over ~14rem because the whole excursion is about five
|
||||
steps of RGB — under a step per 40px, below anything the eye reads as an edge, and
|
||||
the grain dithers the remainder. Keep that shape if this is ever edited: reach
|
||||
--paper at or before 100svh, and get there gradually. Top edge likewise, though it
|
||||
is simpler — the layout viewport's top does not move, so it only needs to arrive.
|
||||
Static, so the layer still composites without repainting per frame. */
|
||||
.ambient::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 5rem;
|
||||
background: linear-gradient(to top, var(--paper), rgb(10 16 12 / 0%));
|
||||
inset: 0;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
var(--paper) 0,
|
||||
rgb(10 16 12 / 0%) 8rem,
|
||||
rgb(10 16 12 / 0%) calc(100svh - 14rem),
|
||||
var(--paper) 100svh,
|
||||
var(--paper) 100%
|
||||
);
|
||||
}
|
||||
|
||||
/* Oversized so the bands can travel a long way without an edge ever entering the
|
||||
@@ -679,14 +713,28 @@ const canonical = new URL('/', Astro.site);
|
||||
which lands on load and leaves it plainly visible. */
|
||||
@supports (animation-timeline: view()) {
|
||||
@media (max-width: 720px) {
|
||||
/* Where the reveal runs, the footer is transparent until it is scrolled to, so
|
||||
opacity is what hides it and the layout no longer has to. That buys back both
|
||||
halves of the drop the fallback needs: the toolbar term goes, because a footer
|
||||
behind Safari's bar cannot show through it at zero alpha, and the clearance
|
||||
shrinks to the little that keeps the rule from being mid-fade at rest. All of
|
||||
it was scroll the reader had to spend before anything began to happen. */
|
||||
.page-shell {
|
||||
--footer-drop: clamp(4.75rem, 9.3vh, 5.1rem);
|
||||
}
|
||||
|
||||
.footer {
|
||||
opacity: 0;
|
||||
animation: footer-reveal linear both;
|
||||
animation-timeline: view();
|
||||
/* Finishes at 88% rather than 100%: the last stretch of "entry" is the
|
||||
element clearing Safari's translucent toolbar, and waiting that long
|
||||
means it is still fading while it looks fully on screen. */
|
||||
animation-range: entry 12% entry 88%;
|
||||
/* "entry" opens before the footer's edge reaches the fold, not at it: parked,
|
||||
it already measures 9-11% entered across phone sizes. So the start has to be
|
||||
past that or the footer sits permanently part-faded at rest — 20% clears it
|
||||
on every size tested with room to spare, and still begins the reveal within
|
||||
the first few pixels of scroll. Ending at 45% means it reads as arrived at
|
||||
roughly a third of the travel, instead of still fading while it already
|
||||
looks fully on screen. */
|
||||
animation-range: entry 20% entry 45%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user