last fade attempt

This commit is contained in:
Vincent van der Wal
2026-08-06 21:37:28 +02:00
parent 810f9c2605
commit d0f94094ca
7 changed files with 77 additions and 45 deletions
+37 -30
View File
@@ -197,56 +197,63 @@
}
/* ── Cross-fades that do not dip ──────────────────────────────────────────
The default cross-fade is NOT opacity-neutral: both snapshots are opaque
and the browser fades one out while fading the other in, so at the
midpoint the pair covers only ~75% of the region and the page background
shows through both. That dip is the flash - over the whole viewport for a
page swap, and over the table, summary and charts (which between them are
the whole content column) for a day switch.
The default cross-fade is NOT opacity-neutral: coverage of two stacked
layers is `new + old * (1 - new)`, so at the midpoint the pair covers only
~75% of the region and the page background shows through both. That dip is
the flash - over the whole viewport for a page swap, and over the table,
summary and charts (between them the whole content column) for a day
switch.
The only opacity-neutral pairing with normal blending is to hold the
outgoing snapshot at full opacity and fade the incoming one in on top of
it - it is painted above - so every frame stays fully covered. */
Two ways out, and which one applies depends on whether the *incoming*
snapshot is opaque. Holding the outgoing one at full opacity fixes the
coverage arithmetic, but a translucent incoming snapshot then reads
straight through it and the old content lingers as a ghost. */
/* The document background is opaque, so the whole-viewport swap can simply
hold the outgoing snapshot until the pseudo elements are torn down. */
@keyframes vt-fade-in {
from {
opacity: 0;
}
}
::view-transition-old(root),
::view-transition-old(day-table),
::view-transition-old(day-summary),
::view-transition-old(day-charts) {
::view-transition-old(root) {
animation: none;
opacity: 1;
}
::view-transition-new(root) {
animation: vt-fade-in 400ms ease;
}
/* The day regions are not opaque - they are cards with gaps and headings
between them - so they keep a real cross-fade and fix the dip the other
way: `plus-lighter` makes the two halves sum to exactly the original
wherever they agree, which is most of the region (the card backgrounds are
the same on both days; only the readings differ). */
::view-transition-old(day-table),
::view-transition-new(day-table),
::view-transition-old(day-summary),
::view-transition-new(day-summary),
::view-transition-old(day-charts),
::view-transition-new(day-charts) {
animation: vt-fade-in 420ms ease;
animation-duration: 420ms;
animation-timing-function: ease;
mix-blend-mode: plus-lighter;
}
/* The outgoing snapshot no longer fades, so a region that gets *shorter*
would keep showing its old tail below the new content for the whole
transition. Clipping to the group - which animates between the two sizes -
turns that into the shrink it actually is. */
::view-transition-group(day-table),
::view-transition-group(day-summary),
::view-transition-group(day-charts) {
overflow: clip;
}
/* Chrome that is identical on both sides of the swap: pinned, never faded.
(Whole-document theme changes are a `root` transition with no page-switch
class, so they still cross-fade the chrome along with everything else.) */
/* Chrome captured only so the fading regions cannot paint over it. The strip
does change - the selected day moves - but that change belongs to the
regions' cross-fade, not to the strip, so it swaps outright: the outgoing
snapshot is dropped rather than held, because the selected cell is a
translucent `bg-primary/10` tint and anything left underneath shows
through it as a second, doubled label. */
::view-transition-old(topbar),
::view-transition-new(topbar),
::view-transition-old(sidebar),
::view-transition-old(daystrip) {
animation: none;
opacity: 0;
}
::view-transition-new(topbar),
::view-transition-new(sidebar),
::view-transition-old(daystrip),
::view-transition-new(daystrip) {
animation: none;
opacity: 1;