React Transitions

Adding smooth animations to React components

✨ What are React Transitions?

React transitions add smooth animations when components appear, update, or disappear. They enhance user experience by making interface changes feel natural and polished instead of abrupt and jarring.


import { CSSTransition } from 'react-transition-group';

function App() {
  const [show, setShow] = useState(true);
  return (
    <CSSTransition in={show} timeout={300} classNames="fade">
      <div>Hello!</div>
    </CSSTransition>
  );
}
                                    

Key Transition Concepts

🎬

CSSTransition

Apply CSS classes during transitions

<CSSTransition
  in={show}
  timeout={300}
/>
📋

TransitionGroup

Manage multiple transitioning elements

<TransitionGroup>
  {items.map(...)}
</TransitionGroup>
⏱️

Timeout

Control animation duration

timeout={300}
// or
timeout={{
  enter: 300,
  exit: 200
}}
🎨

Class Names

Define transition CSS classes

.fade-enter {
  opacity: 0;
}
.fade-enter-active {
  opacity: 1;
}

🔹 Installing React Transition Group

React Transition Group is the official library for adding transitions to React components. It provides low-level components for defining entering and exiting transitions, making animations smooth and performant.

# Install react-transition-group
npm install react-transition-group

# or with yarn
yarn add react-transition-group

Note: This library works with CSS transitions and animations.

🔹 Basic Fade Transition

A fade transition smoothly changes opacity when elements appear or disappear. This is one of the most common and subtle animations, perfect for modals, tooltips, and notifications in your application.

// FadeExample.jsx
import { useState } from 'react';
import { CSSTransition } from 'react-transition-group';
import './fade.css';

function FadeExample() {
  const [show, setShow] = useState(true);

  return (
    <div>
      <button onClick={() => setShow(!show)}>
        Toggle
      </button>
      
      <CSSTransition
        in={show}
        timeout={300}
        classNames="fade"
        unmountOnExit
      >
        <div className="box">
          I fade in and out!
        </div>
      </CSSTransition>
    </div>
  );
}
/* fade.css */
.fade-enter {
  opacity: 0;
}

.fade-enter-active {
  opacity: 1;
  transition: opacity 300ms ease-in;
}

.fade-exit {
  opacity: 1;
}

.fade-exit-active {
  opacity: 0;
  transition: opacity 300ms ease-out;
}

.box {
  padding: 20px;
  background: #3498db;
  color: white;
  border-radius: 8px;
}

🔹 Slide Transition

Slide transitions move elements in from the side, creating a dynamic entrance effect. They're ideal for sidebars, drawers, and mobile menus, providing clear visual feedback about content appearing or disappearing.

// SlideExample.jsx
import { useState } from 'react';
import { CSSTransition } from 'react-transition-group';
import './slide.css';

function SlideExample() {
  const [show, setShow] = useState(false);

  return (
    <div>
      <button onClick={() => setShow(!show)}>
        {show ? 'Hide' : 'Show'} Panel
      </button>
      
      <CSSTransition
        in={show}
        timeout={300}
        classNames="slide"
        unmountOnExit
      >
        <div className="panel">
          <h3>Side Panel</h3>
          <p>This slides in from the right!</p>
        </div>
      </CSSTransition>
    </div>
  );
}
/* slide.css */
.slide-enter {
  transform: translateX(100%);
}

.slide-enter-active {
  transform: translateX(0);
  transition: transform 300ms ease-out;
}

.slide-exit {
  transform: translateX(0);
}

.slide-exit-active {
  transform: translateX(100%);
  transition: transform 300ms ease-in;
}

.panel {
  position: fixed;
  right: 0;
  top: 0;
  width: 300px;
  height: 100vh;
  background: white;
  box-shadow: -2px 0 8px rgba(0,0,0,0.1);
  padding: 20px;
}

🔹 TransitionGroup for Lists

TransitionGroup manages transitions for multiple children, perfect for dynamic lists. It automatically handles adding and removing items with smooth animations, making list updates feel polished and professional in your application.

// ListExample.jsx
import { useState } from 'react';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import './list.css';

function ListExample() {
  const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3']);

  const addItem = () => {
    const newItem = `Item ${items.length + 1}`;
    setItems([...items, newItem]);
  };

  const removeItem = (index) => {
    setItems(items.filter((_, i) => i !== index));
  };

  return (
    <div>
      <button onClick={addItem}>Add Item</button>
      
      <TransitionGroup className="list">
        {items.map((item, index) => (
          <CSSTransition
            key={item}
            timeout={300}
            classNames="item"
          >
            <div className="list-item">
              {item}
              <button onClick={() => removeItem(index)}>
                Remove
              </button>
            </div>
          </CSSTransition>
        ))}
      </TransitionGroup>
    </div>
  );
}
/* list.css */
.item-enter {
  opacity: 0;
  transform: translateY(-20px);
}

.item-enter-active {
  opacity: 1;
  transform: translateY(0);
  transition: all 300ms ease-out;
}

.item-exit {
  opacity: 1;
  transform: translateX(0);
}

.item-exit-active {
  opacity: 0;
  transform: translateX(100%);
  transition: all 300ms ease-in;
}

.list-item {
  padding: 15px;
  margin: 10px 0;
  background: #ecf0f1;
  border-radius: 4px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

🔹 Modal with Transition

Modals with transitions create professional overlay effects. Combining fade and scale animations makes dialogs appear smoothly, improving user experience and making your application feel more polished and responsive.

// Modal.jsx
import { CSSTransition } from 'react-transition-group';
import './modal.css';

function Modal({ show, onClose, children }) {
  return (
    <CSSTransition
      in={show}
      timeout={300}
      classNames="modal"
      unmountOnExit
    >
      <div className="modal-overlay" onClick={onClose}>
        <div className="modal-content" onClick={(e) => e.stopPropagation()}>
          {children}
          <button onClick={onClose}>Close</button>
        </div>
      </div>
    </CSSTransition>
  );
}

// Usage
function App() {
  const [showModal, setShowModal] = useState(false);
  
  return (
    <div>
      <button onClick={() => setShowModal(true)}>
        Open Modal
      </button>
      
      <Modal show={showModal} onClose={() => setShowModal(false)}>
        <h2>Modal Title</h2>
        <p>This is a modal with smooth transitions!</p>
      </Modal>
    </div>
  );
}
/* modal.css */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
}

.modal-content {
  background: white;
  padding: 30px;
  border-radius: 8px;
  max-width: 500px;
}

.modal-enter {
  opacity: 0;
}

.modal-enter .modal-content {
  transform: scale(0.9);
}

.modal-enter-active {
  opacity: 1;
  transition: opacity 300ms;
}

.modal-enter-active .modal-content {
  transform: scale(1);
  transition: transform 300ms;
}

.modal-exit {
  opacity: 1;
}

.modal-exit-active {
  opacity: 0;
  transition: opacity 300ms;
}

🧠 Test Your Knowledge

Which prop controls the duration of a transition?