16: Transitions & "Wow" Without JS

Motion for polish, not for nausea. A little transform and transition makes any site feel alive without JavaScript.

Transition: smooth between states

transition: transform 120ms ease
.btn {
  transition: transform 120ms ease, background 150ms ease;
}
.btn:hover  { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
PropExampleNotes
transitiontransition: opacity 200ms easeproperty plus duration plus timing
transformtranslateY(-4px), scale(1.05)GPU-friendly, does not reflow
opacity0 to 1Also cheap to animate
Animate cheap properties: transform and opacity are smooth (GPU). Avoid animating width, height, or margin. They trigger layout and cause jank.

Transforms: move, scale, rotate

translateY(-6px)
scale(1.15)
rotate(6deg)
.a { transform: translate(-50%, -50%); } /* callback to Module 7 */
.b { transform: scale(1.05); }
.c { transform: rotate(6deg); }
.d { transform: translateY(-4px) scale(1.02); } /* combine */

Animation and @keyframes

Loading…
shimmer
/* spinner */
.spinner {
  width: 28px; height: 28px;
  border: 3px solid #ddd;
  border-top-color: #0b57d0;
  border-radius: 50%;
  animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* shimmer placeholder */
.shimmer {
  background: linear-gradient(90deg,#eee 25%,#f8f8f8 50%,#eee 75%);
  background-size: 200% 100%;
  animation: shimmer 1.2s infinite;
}
@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

prefers-reduced-motion: respect the user

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

Some users disable animations (vestibular disorders). This query turns off motion for them. Include it.

Gotcha: Do not use infinite loops on content. Spinners are only for loading. Decorative infinite animation is distracting and hurts battery.

Live demo: card hover and spinner

Hover me
translateY + shadow
pure CSS spinner
shimmer bar
.card {
  transition: transform 180ms ease, box-shadow 180ms ease;
}
.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(0,0,0,0.12);
}
Exercise: Card hover and loading spinner (15 min)
  1. Take a card from Module 09 or 14 and add transition: transform 180ms ease, box-shadow 180ms ease.
  2. Add :hover { transform: translateY(-4px); box-shadow: … }
  3. Build the spinner with border-top-color and @keyframes spin.
  4. Add @media (prefers-reduced-motion: reduce) { * { animation: none !important; } }.
Prev15: Forms & Inputs Next17: Capstone