name: motion-and-hover-polish description: Donnez à une interface un tempo commun et un petit vocabulaire de micro-interactions au survol et d'état : paliers de durée (tap/pop/hover/card/layout) pour CSS et Motion, échanges de swap, lignes dont la surbrillance s'agrandit, flèches de suivi, coups de pouce de chevron, soulèvements de carte sans translate, dégradés de bord de défilement, et échanges d'icônes/étiquettes pour les boutons de copie et de bascule. À utiliser lorsque les animations semblent incohérentes, les durées sont des nombres magiques dispersés, les survols ne changent que la couleur, ou qu'un produit semble plat ou inachevé. Déclenché sur : durée d'animation, timing de transition, état de survol, micro-interaction, polissage, retour de bouton de copie, icône de menu pour fermer, flèche retour, survol de carte, dégradé de défilement, jetons de mouvement, durées Framer Motion. license: MIT
Paliers de mouvement et recettes de survol
Deux idées, éprouvées dans 17 prototypes d'applications :
- Les durées sont une échelle, pas un nombre par composant. L'œil lit un tempo partagé comme celui d'un seul produit. Les éléments plus petits se déplacent plus vite.
- Les survols modifient la géométrie, doucement. Une surbrillance qui grandit dans la ligne, une flèche qui arrive, un chevron qui s'incline vers sa destination, une étiquette qui roule vers son état suivant. Les survols qui ne changent que la couleur donnent l'impression d'un interrupteur qui bascule.
Fichiers
references/recipes.css: jetons@themeTailwind v4 et recettes@utility.references/timing.ts: les mêmes paliers pour Motion et WAAPI.references/swap.tsx:IconSwapetLabelSwap(React).
Paliers
| Palier | ms | Pour |
|---|---|---|
tap | 100 | une icône qui change, une pression |
pop | 150 | un menu, une popover ou une infobulle qui s'ouvre |
hover | 200 | une ligne ou un contrôle qui répond au pointeur |
card | 300 | une carte qui se soulève, une liste qui se stabilise, un changement de page |
layout | 500 | un panneau qui se réduit, la page qui se remet en page |
- Les entrées ralentissent (
cubic-bezier(0.22,1,0.36,1)). Les sorties accélèrent et sont plus courtes d'un palier. - Lorsque deux éléments échangent leur place, celui qui sort part immédiatement et celui qui entre commence avec un délai de
delay-handoff(50ms). - Les interpolations de valeurs (un compteur, une barre de progression, un tracé de graphique) peuvent être plus longues : l'œil suit les données.
- Conservez les ressorts intentionnels.
Migration : associez chaque durée ad hoc au palier le plus proche.
| Valeur ad hoc | Palier |
|---|---|
| 0.12 | tap |
| 0.15–0.18 | pop |
| 0.2–0.24 | hover |
| 0.28–0.35 | card |
| 0.4–0.5 | layout |
Attendez-vous à ce que le timing à l'écran change de moins de 20ms presque partout.
Recettes (une par élément)
hover-grow(lignes de navigation, liens) :- La surbrillance est un
::beforequi commence en retrait (3 px sur 6 px) et transparent, puis gonfle jusqu'à occuper toute la ligne en fondu. - Elle apparaît aussi pour
:focus-visible,data-state=openetaria-current=page. - Les designs carrés ou bruts (type Carbon) doivent conserver une surbrillance plate à la place.
- La surbrillance est un
trail(liens, "Parcourir les forfaits") :- Un glyphe de suivi à demi-échelle et transparent jusqu'à ce que le parent
.groupsoit survolé ou focusé, grandissant depuis son bord avant. trail-out(grandit depuis le coin inférieur gauche) plusarrow-up-rightmarque les liens qui quittent l'application.
- Un glyphe de suivi à demi-échelle et transparent jusqu'à ce que le parent
nudge/nudge-back(chevrons, "Voir tout", liens retour) : une inclinaison de 2 px vers la destination.lift(cartes cliquables) :- Un ton de surface plus clair et une ombre plus profonde, sur le palier
card. - Jamais de translate : une carte qui saute sous le curseur déplace la chose visée.
- Un ton de surface plus clair et une ombre plus profonde, sur le palier
scroll-fade(panneaux défilants) :- Dégradés de bord basés sur un masque, uniquement sur un côté qui peut encore défiler. Il est piloté par la timeline de défilement du conteneur lui-même et n'a besoin d'aucune couleur de fond.
- Les navigateurs non pris en charge n'affichent simplement aucun dégradé.
IconSwap(menu en fermer, copier en vérifié, soleil en lune) :- Le glyphe sortant rétrécit, s'incline de −22° et disparaît en fondu avec un ease-in.
- Le suivant suit après le délai de transfert.
- Les deux restent montés, donc l'inversion se fait proprement en plein vol.
LabelSwap("Copier le lien" en "Copié", "Réduire" en "Agrandir") :- Les deux étiquettes sont dans une seule cellule de grille, donc pas de saut de largeur.
- L'étiquette cachée devient
invisibleviatransition-discrete, donc les technologies d'assistance n'entendent que l'étiquette actuelle.
Pièges
scroll-fadesur un élément qui s'anime lui-même (menu Radix, popover ou contenu de select) remplace l'animation de sortie de cet élément. Radix attend une sortie qui ne se termine jamais, et le menu reste ouvert. Placez le dégradé sur un enfant défilant à l'intérieur.scroll-fademasque aussi les bordures et les ombres. Ne le mettez pas sur une carte bordée ; placez-le sur le défileur intérieur.- Les utilitaires
duration-*personnalisés dans Tailwind v4 doivent aussi définir--tw-duration, sinon une utilitairetransition-[...]sur le même élément gagne selon l'ordre de tri. - Les étapes de type nommé qui portent une hauteur de ligne (
--text-meta--line-height) décalent chaque ligne convertie d'un pixel lors du remplacement de tailles arbitraires qui héritent du leading du parent. Donnez aux étapes intermédiaires aucune hauteur de ligne propre. - Limitez les survols derrière
@media (hover: hover). Affichez le même état sur:focus-visible, et respectezprefers-reduced-motion(Motion :<MotionConfig reducedMotion="user">).