React / React Transitions / CSS Transitions in React
Home /React /React Transitions /CSS Transitions in React

CSS Transitions in React

CSS Transitions in React

The most performant transitions are pure CSS. React’s job is simply to toggle class names; the browser’s compositor thread handles the animation. Properties that can be animated on the compositor thread (without involving the main thread) are: opacity, transform. Prefer these over animating width, height, or color.

4.1 Basic CSS Transition: Fade Toggle

FadeToggle.js

import { useState } from 'react';
import './FadeToggle.css';

export default function FadeToggle() {
  const [visible, setVisible] = useState(true);

  return (
    <div className="wrapper">
      <div className={`box ${visible ? 'visible' : 'hidden'}`}>
        Hello, I fade in and out!
      </div>
      <button onClick={() => setVisible(v => !v)}>
        Toggle
      </button>
    </div>
  );
}

FadeToggle.cs

.box {
  transition: opacity 300ms ease, transform 300ms ease;
}

.box.visible {
  opacity: 1;
  transform: translateY(0);
}

.box.hidden {
  opacity: 0;
  transform: translateY(-8px);
}

/* Respect user preference for reduced motion */
@media (prefers-reduced-motion: reduce) {
  .box { transition: none; }
}
Tip: CSS transitions only interpolate between two states. For enter/exit on mount/unmount (when the element leaves the DOM entirely), you need react-transition-group or Framer Motion, CSS alone cannot animate an element before it is removed from the DOM.

4.2 CSS Keyframe Animation: Entrance

SlideIn.css

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

.card-enter {
  animation: slideInUp 400ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* Stagger children with animation-delay */
.card-enter:nth-child(1) { animation-delay: 0ms; }
.card-enter:nth-child(2) { animation-delay: 80ms; }
.card-enter:nth-child(3) { animation-delay: 160ms; }

4.3 Inline Style Transitions

For dynamic values (e.g. a progress bar driven by state), use inline styles with a CSS transition on the element:

ProgressBar.jsx

function ProgressBar({ value }) {          // value: 0 – 100
  return (
    <div style={{ background: '#1f2840', borderRadius: 99, height: 8 }}>
      <div
        style={{
          width: `${value}%`,
          height: '100%',
          background: '#61dafb',
          borderRadius: 'inherit',
          transition: 'width 500ms cubic-bezier(0.4, 0, 0.2, 1)',
        }}
      />
    </div>
  );
}

References:
React Community
Intro to React