Merge nucleic/upbeat-jade-ibis-kt5e into main
Mirrored from corpo b66f72d.
This commit is contained in:
+50
-28
@@ -218,21 +218,28 @@ const canonical = new URL('/', Astro.site);
|
||||
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.
|
||||
Nor can that band be held flat, which was the next thing tried and the next thing
|
||||
to fail. Reaching --paper at 100svh and holding it to 100lvh does put the same
|
||||
paint at both places the edge can rest — but it also creates ~220px of dead colour
|
||||
under a lit field, and a hard fling overscrolls far enough to expose the whole of
|
||||
it at once. It read as a dark bar, correctly: it was one. Dodging a moving
|
||||
boundary by flattening the region it moves through is still a patch, and a fast
|
||||
scroll is all it took to find it.
|
||||
|
||||
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. */
|
||||
So neither the value nor its slope may jump anywhere the viewport can reach. The
|
||||
field decays continuously and never stops decaying: by 100svh it is within a
|
||||
fraction of one RGB step of --paper, and it spends the rest of the way to 100lvh
|
||||
closing that fraction. Both candidate edges match the strip beyond them to well
|
||||
under the grain, there is no flat stretch for an overscroll to reveal, and there
|
||||
is no point along the run where the rate visibly changes. The whole excursion is
|
||||
about twelve steps of RGB spread over half the screen, so what this reads as is a
|
||||
light that falls off toward the bottom — which is the intent, not a correction.
|
||||
|
||||
If this is ever edited, the property to keep is that shape: monotonic, no flat
|
||||
stretch below 100svh, and near-nothing of the field left by the time the edge can
|
||||
land on it. Do not reintroduce a stop that arrives at --paper and sits there. Top
|
||||
edge is simpler — the layout viewport's top does not move, so it only has to
|
||||
arrive. Static, so the layer still composites without repainting per frame. */
|
||||
.ambient::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
@@ -241,8 +248,11 @@ const canonical = new URL('/', Astro.site);
|
||||
to bottom,
|
||||
var(--paper) 0,
|
||||
rgb(10 16 12 / 0%) 8rem,
|
||||
rgb(10 16 12 / 0%) calc(100svh - 14rem),
|
||||
var(--paper) 100svh,
|
||||
rgb(10 16 12 / 0%) 48%,
|
||||
rgb(10 16 12 / 35%) 70%,
|
||||
rgb(10 16 12 / 70%) 80%,
|
||||
rgb(10 16 12 / 93%) 86%,
|
||||
rgb(10 16 12 / 98.5%) 92%,
|
||||
var(--paper) 100%
|
||||
);
|
||||
}
|
||||
@@ -711,7 +721,7 @@ const canonical = new URL('/', Astro.site);
|
||||
come up the screen. Scroll-driven animations are still the newest thing here, so
|
||||
this stays behind @supports: without it the footer keeps the timed fade above,
|
||||
which lands on load and leaves it plainly visible. */
|
||||
@supports (animation-timeline: view()) {
|
||||
@supports (animation-timeline: scroll()) {
|
||||
@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
|
||||
@@ -725,23 +735,35 @@ const canonical = new URL('/', Astro.site);
|
||||
|
||||
.footer {
|
||||
opacity: 0;
|
||||
animation: footer-reveal linear both;
|
||||
animation-timeline: view();
|
||||
/* "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%;
|
||||
animation: footer-reveal ease-out both;
|
||||
/* The scroller, not view(). view() measures the footer against the fold, so
|
||||
the reveal is a window inside the footer's own height — and the footer is
|
||||
short. Every usable window was a fraction of an already short travel: the
|
||||
fade got ~22px of the 78px the reader has, which is not a fade, it is a
|
||||
snap. It also had to start past ~20% because "entry" opens before the
|
||||
footer's edge reaches the fold, so the footer would otherwise sit part-faded
|
||||
at rest — the offsets were fighting the geometry.
|
||||
|
||||
Against the scroller the two ends of the reveal are the two ends of the
|
||||
scroll. Nothing is cropped and nothing needs offsetting: exactly 0 at rest,
|
||||
exactly 1 at the bottom, and every pixel of thumb travel in between spent
|
||||
fading. Same distance to scroll as before, three and a half times the
|
||||
distance to fade over. It holds for any phone, because the range is defined
|
||||
by the scroll rather than by the footer's height relative to the screen.
|
||||
|
||||
Safe against a zero-length scroll — the drop below always adds some, and
|
||||
this is inside the phone breakpoint besides. */
|
||||
animation-timeline: scroll(root block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The lift is small on purpose. Over a travel this short a large one reads as the
|
||||
footer being dragged rather than arriving, and it is the movement, not the fade,
|
||||
that the eye catches as a jolt. */
|
||||
@keyframes footer-reveal {
|
||||
from {
|
||||
transform: translate3d(0, 1.15rem, 0);
|
||||
transform: translate3d(0, 0.55rem, 0);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
|
||||
Reference in New Issue
Block a user