Skip to main content
Gremorie

Motion

Easing curves, canonical durations and bundled animations - temporal feedback between one state and the next.

Motion is the temporal grammar of the interface. When a button changes color instantly, it feels broken. When it changes over 600ms, it feels lazy. The 100-300ms range is where human perception resonates with state change in UI.

Transitions vs. animations

Two motion families with different jobs:

  • Transitions happen between two states (button hover, drawer opening, tab switch). Use transition-* + duration-* + ease-*.
  • Animations run continuously or in a discrete loop (loaders, pulses, skeletons). Use animate-*.

The general rule: prefer transitions - they are driven by state, so the motion is always semantically justified. Animations spend attention, so use them when continuity is the point (loading, pulsing for attention).

Easing

Three curves cover 95% of cases. For the rest (bouncy, elastic, overshoot), use Tailwind's arbitrary syntax: ease-[cubic-bezier(0.34,1.56,0.64,1)].

TokenClasseCurvaUso
--ease-inease-incubic-bezier(0.4, 0, 1, 1)Saídas — elemento começa lento e acelera para fora
--ease-outease-outcubic-bezier(0, 0, 0.2, 1)Entradas — elemento entra rápido e desacelera (mais natural)
--ease-in-outease-in-outcubic-bezier(0.4, 0, 0.2, 1)Transições simétricas — toggles, expansões

Duration

Gremorie does not declare dedicated variables for duration-* - Tailwind v4 already generates duration-75, duration-100, and so on, which write the milliseconds directly. The global default (when no duration is specified on transition) is 150ms, set by --default-transition-duration.

FaixaDuraçãoUso
Default150msTransições padrão de UI (hover, focus)
Fast75-100msMicrointerações imperceptíveis (cor, opacity)
Medium200-300msAcordeões, drawers, dialogs
Slow400-500msPage transitions, animações narrativas

Bundled animations

Tailwind v4 ships four general-purpose animations. You can add more via @theme (in consuming projects), but these cover the main cases.

TokenClasseDefiniçãoUso
--animate-spinanimate-spinspin 1s linear infiniteLoaders rotativos
--animate-pinganimate-pingping 1s cubic-bezier(0, 0, 0.2, 1) infinitePulsos de notificação (badge não-lida)
--animate-pulseanimate-pulsepulse 2s cubic-bezier(0.4, 0, 0.6, 1) infiniteSkeletons, placeholders de loading
--animate-bounceanimate-bouncebounce 1s infiniteIndicadores de scroll, chamados de atenção

Best practices

  • Use ease-out for entrances and ease-in for exits. It is counter-intuitive, but it matches physical perception: objects decelerate as they arrive and accelerate as they leave the field of view.
  • 150ms is the sweet spot for UI transitions. Faster looks like a glitch, slower feels lazy.
  • 300ms+ is narrative-animation territory - drawer opening, page transitions. Above 500ms you are making the user wait.
  • Respect prefers-reduced-motion. In Gremorie components, critical motion (loaders) stays, but decorative motion (parallax, swooshes) should be disabled:
    @media (prefers-reduced-motion: reduce) {
      .my-fancy-animation {
        animation: none;
      }
    }
  • Do not animate everything at once. If a transition touches 5 properties, ask whether 2 or 3 would do - parallel motion turns into visual noise fast.

On this page