Was macht Bewegungsabstufungen und Hover-Rezepte?
Zwei Ideen, bewährt in 17 Prototyp-Apps:
- Dauern sind eine Skala, keine Zahl pro Komponente. Das Auge liest ein gemeinsames Tempo als ein Produkt. Kleinere Dinge bewegen sich schneller.
- Hover verändert die Geometrie, sanft. Eine Hervorhebung, die in die Zeile hineinwächst, ein Pfeil, der ankommt, ein Chevron, das sich in die Richtung neigt, in die es geht, ein Label, das in seinen nächsten Zustand rollt. Nur farbliche Hover wirken wie ein Schalter, der umlegt.
Dateien
references/recipes.css: Tailwind v4@theme-Tokens und@utility-Rezepte.references/timing.ts: Dieselben Abstufungen für Motion und WAAPI.references/swap.tsx:IconSwapundLabelSwap(React).
Abstufungen
| Abstufung | ms | Verwendung |
|---|---|---|
tap | 100 | Ein Icon, das wechselt, ein Drücken |
pop | 150 | Ein Menü, Popover oder Tooltip öffnet sich |
hover | 200 | Eine Zeile oder ein Steuerelement antwortet auf den Zeiger |
card | 300 | Eine Karte hebt sich, eine Liste setzt sich, ein Seitenwechsel |
layout | 500 | Ein Panel klappt zusammen, die Seite fließt um |
- Eintritte easing-out (
cubic-bezier(0.22,1,0.36,1)). Austritte easing-in und laufen eine Abstufung kürzer. - Wenn zwei Dinge die Plätze tauschen, verlässt das ausgehende sofort und das eingehende startet mit
delay-handoff(50ms) Verzögerung. - Wert-Tweens (ein Zähler, ein sich füllender Balken, eine sich zeichnende Diagrammlinie) dürfen länger laufen: Das Auge folgt den Daten.
- Absichtliche Federn beibehalten.
Migration: Jede ad-hoc Dauer der nächsten Abstufung zuordnen.
| Ad-hoc-Wert | Abstufung |
|---|---|
| 0.12 | tap |
| 0.15–0.18 | pop |
| 0.2–0.24 | hover |
| 0.28–0.35 | card |
| 0.4–0.5 | layout |
Erwarten Sie, dass sich die Timing auf dem Bildschirm fast überall um unter 20ms ändert.
Rezepte (eines pro Element)
hover-grow(Navigationszeilen, Linkzeilen):- Die Hervorhebung ist ein
::before, das innenliegend (3px mal 6px) und transparent beginnt und dann zur vollen Zeile anschwillt, während es einblendet. - Es zeigt sich auch bei
:focus-visible,data-state=openundaria-current=page. - Quadratische oder brutalistische Designs (Carbon-ähnlich) sollten stattdessen eine flache Hervorhebung verwenden.
- Die Hervorhebung ist ein
trail(Linkzeilen, „Pläne durchsuchen“):- Ein nachlaufendes Glyph in halber Größe und transparent, bis das übergeordnete
.groupgehovt oder fokussiert wird, wobei es von seiner Vorderkante her wächst. trail-out(wächst von unten links) plusarrow-up-rightmarkiert Links, die die App verlassen.
- Ein nachlaufendes Glyph in halber Größe und transparent, bis das übergeordnete
nudge/nudge-back(Chevrons, „Alle anzeigen“, Zurück-Links): eine 2px-Neigung in Richtung des Ziels.lift(klickbare Karten):- Eine Oberflächenstufe heller und eine Schattenstufe tiefer, über der
card-Abstufung. - Niemals translate: Eine Karte, die unter dem Cursor springt, bewegt das, worauf gezielt wird.
- Eine Oberflächenstufe heller und eine Schattenstufe tiefer, über der
scroll-fade(scrollende Bereiche):- Maskenbasierte Randausblendungen, nur auf einer Seite, die noch scrollen kann. Sie wird vom eigenen Scroll-Zeitplan des Containers gesteuert und benötigt keine Hintergrundfarbe.
- Nicht unterstützte Browser zeigen einfach keine Ausblendung.
IconSwap(Menü zu Schließen, Kopieren zu Haken, Sonne zu Mond):- Das ausgehende Glyph schrumpft, neigt sich um −22° und blendet mit ease-in aus.
- Das eingehende folgt nach der Übergabeverzögerung.
- Beide bleiben montiert, sodass es sich sauber mitten im Flug umkehren lässt.
LabelSwap(„Link kopieren“ zu „Kopiert“, „Einklappen“ zu „Ausklappen“):- Beide Labels sitzen in einer Gitterzelle, sodass es keinen Breitensprung gibt.
- Das verborgene Label geht über
transition-discreteaufinvisible, sodass assistive Technologien nur das aktuelle hören.
Fallen
scroll-fadeauf einem Element, das sich selbst animiert (Radix-Menü, Popover- oder Select-Inhalt) ersetzt dessen Exit-Animation. Radix wartet auf einen Exit, der nie endet, und das Menü bleibt offen. Setzen Sie die Ausblendung auf ein scrollendes Kindelement im Inneren.scroll-fademaskiert auch Rahmen und Schatten. Nicht auf eine Karte mit Rahmen setzen; sondern auf den inneren Scroller.- Benutzerdefinierte
duration-*-Utilities in Tailwind v4 müssen auch--tw-durationsetzen, sonst gewinnt einetransition-[…]-Utility auf demselben Element je nach Sortierreihenfolge. - Benannte Typ-Schritte, die eine Zeilenhöhe mitführen (
--text-meta--line-height) verschieben jede konvertierte Zeile um ein Pixel, wenn man willkürliche Größen ersetzt, die die Zeilenhöhe des Elternelements geerbt haben. Geben Sie Zwischenschritten keine eigene Zeilenhöhe. - Hover hinter
@media (hover: hover)schalten. Denselben Zustand bei:focus-visibleanzeigen undprefers-reduced-motionrespektieren (Motion:<MotionConfig reducedMotion="user">).