Animations
Everything that moves in Yeti reads a duration token, and that is what makes reduced motion work.
Durations collapse, end states stay
Yeti never removes an effect for a reader who has asked for less motion. It shortens it. Every animation and transition in the framework reads --yeti-duration-fast or --yeti-duration-base, and under prefers-reduced-motion: reduce both collapse to 0.01ms. A dialog still opens, a card still lifts, a lift still changes colour. They simply arrive rather than travel.
That is a deliberate choice over animation: none. An effect switched off mid-way can strand an element somewhere its layout did not put it, and the reader is left looking at a half-open panel or nothing at all. A collapsed duration always ends where the CSS says it ends.
It is also why the reset's universal rule is not the mechanism. A declaration in the components layer outranks a universal one in the reset, so that rule only reaches animation the browser or a third party brought. Yeti's own motion is stilled by its tokens.
Utilities that are entirely about movement carry their own pair, so tuning one gesture never moves another: enter has --yeti-enter-duration, lift has its own distance and shadow, and page transitions have --yeti-page-duration.
Page transitions
A browser can crossfade between two documents instead of snapping, with no script. Yeti does not turn this on. Turn it on in your own stylesheet, with one rule:
@view-transition { navigation: auto; }
Both pages need it and they must be same-origin, so for a site built on one stylesheet it is on everywhere or nowhere.
Yeti leaves that rule to you for two reasons. Cross-document view transitions are below Baseline, and Yeti's rule is that a feature below Baseline is guarded rather than assumed. There is also nothing to guard it with: @view-transition is an at-rule with no element to select, so unlike every other opt-in in Yeti it cannot hang off a class. Where the feature is missing, Firefox as this is written, the navigation just snaps and nothing is broken.
What Yeti does supply is the timing:
| Token | Default | |
|---|---|---|
--yeti-page-duration |
200ms |
How long the crossfade takes |
--yeti-page-ease |
ease |
The curve it runs on |
The animation itself stays the browser's. Its crossfade already blends the two snapshots correctly, which a hand-written pair of opacity keyframes does not: those dip through the page background halfway unless they also carry mix-blend-mode. Yeti changes when it runs, not what it does.
Re-timing it is also the only way to honour reduced motion here. No selector reaches an at-rule, and the reset's universal rule does not match a ::view-transition pseudo-element, so the collapsed --yeti-page-duration is what stills the crossfade. Write your own view-transition animations and you take that back on yourself, so read the same two tokens if you do.
A page transition is a whole-page crossfade and nothing more. Carrying one element across two pages needs view-transition-name on both, which Yeti has no vocabulary for yet.