Skip to main content

Motion Philosophy

Every animation must answer: what does this communicate that stillness cannot? Motion exists to reduce cognitive load, not increase visual complexity.

Purposeful

Motion communicates state change. No decorative animation.

Subtle

Users should feel the effect, not notice the animation.

Consistent

One easing curve for coherent motion language.

Reducible

Always respect prefers-reduced-motion.

Duration

Five duration levels from instant feedback to deliberate reveals.

Easing

Consistent easing creates coherent motion. Use --ease-standard for most transitions.

--ease-standard

Default easing

Most transitions

--ease-decelerate

Enter screen

Elements appearing

--ease-accelerate

Leave screen

Elements disappearing

View Transitions

Property-specific transition speeds reflect their ontological character.

.agency 200ms Efficient, direct
.io 250ms Measured, analytical
.space 300ms Exploratory, playful

Gradient principle: Motion speed reflects epistemic stance. Commercial work demands efficiency; philosophical foundation requires dwelling.

Anti-Patterns

Avoid these common motion mistakes.

Decorative animation

Bouncing icons, pulsing elements, attention-seeking motion.

Duration > 500ms

Feels sluggish. Users wait for UI, not watch it.

Custom easing curves

Breaks motion coherence. One curve for all.

Animating layout properties

Avoid width, height. Use transform instead.

Reduced Motion

Always respect user preferences. Some users experience motion sickness or vestibular disorders.

reduced-motion.css
@media (prefers-reduced-motion: reduce) {
  *, *: :before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Usage

motion-usage.css
/* Hover transitions */
.button {
  transition: all var(--duration-micro) var(--ease-standard);
}

.button: hover {
  background: var(--color-hover);
}

/* Modal entrance */
.modal {
  animation: fadeIn var(--duration-standard) var(--ease-decelerate);
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *: :before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}