Skip to main content

How to Create an Animated Accordion With React JS

Saleh is an experienced Web Developer and uses his knowledge and experience to guide people looking to learn Web Dev and new technologies

Accordion

Accordion

In this post, we will learn how to create an animated accordion in React JS. We will be creating a Simple Accordion that will have spring animations from React Spring. React Spring is a physics-based animation library that makes animation very easy to apply in React JS.

You can see the working accordion and the code on this sandbox.

Creating a React App

Firstly, create a React application. If you do not know how to do this, then check out this video.

Add the following code to your App.js. We will have a main div inside, which will have a heading and the accordion. The accordion itself will be a separate component that we will re-use. We will also import App.css (if it is not created by default, you can create it).

import React from "react";
import "./App.css";

function App() {

  return (
    <div className="main">
      <h1>React Accordion</h1>
      <div className="accordion">
      </div>
    </div>
  );
}

export default App;

Accordion Component

Next we will create the accordion component. The arrow icon will be from material-ui icons. You can install material ui icons with the following command:

npm install @mui/icons-material

import { React, useState } from "react";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";

function Accordion(props) {
  return (
    <div className="accordion__item">
      <div className="accordion__header">
        <h4>{props.title}</h4>
        <i>
          <ExpandMoreIcon />
        </i>
      </div>
      <p className="accordion__content">{props.text}</p>
    </div>
  );
}

export default Accordion;

Accordion Content

We will pass the accordion content as a prop from App.js. Inside App.js, we will import the accordion and call it as many times we want. Basically, we are reusing the component, but we can change the text with the help of the props. The title and text can be set for each accordion individually.

import React from "react";
import "./App.css";
import Accordion from "./Components/Accordion";

function App() {
  return (
    <div className="main">
      <h1>React Accordion</h1>
      <div className="accordion">
        <Accordion
          title="Item 1 - Lorem ipsum dolor sit amet"
          text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam"
        />
        <Accordion
          title="Item 2 - Lorem ipsum dolor sit amet"
          text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam"
        />
        <Accordion
          title="Item 3 - Lorem ipsum dolor sit amet"
          text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam"
        />
        <Accordion
          title="Item 4 - Lorem ipsum dolor sit amet"
          text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam"
        />
      </div>
    </div>
  );
}

export default App;

Style the Accordion

Our basic accordion is created. Now we need to create the functionality and style it. Add the following CSS to App.css.

App.css

* {
    margin: 0;
    padding: 0;
    background-color: #1c2938;
}

.main {
    display: flex;
    height: 100vh;
    width: 100%;
    align-items: center;
    flex-direction: column;
    row-gap: 20px;
}

h1 {
    margin: 10px;
    font-size: 40px;
    color: rgb(255, 255, 255);
}

.accordion {
    margin: 30px;
    width: fit-content;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.accordion__item {
    width: 40%;
    max-height: 25px;
    padding: 17px 10px;
    border-bottom: 1px solid #c9c9c9;
    color: #fff;
    overflow: hidden;
    cursor: pointer;
}

.accordion__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.accordion__header h4 {
    transition: 0.2s ease-in-out;
    font-size: 16px;
    font-weight: 400;
    margin-bottom: 10px;
}

.accordion__header i {
    transition: 0.2s ease-in-out;
    transform-origin: center;
    margin-bottom: 10px;
}

.accordion__header:hover h4 {
    color: #10d6f5!important;
}

.accordion__header:hover i {
    color: #10d6f5;
}

.accordion__content {
    margin: 5px;
}

@media (max-width:600px) {
    h1 {
        font-size: 30px;
    }
    .accordion__item {
        width: 80%;
    }
}

Your accordion is basically created at this point. Only the functionality is left. At this point it will be looking like this.

Output

Output

Accordion Functionality

For the open and close functionality, we will create a state called open inside Accordion.js. The state will be toggled from true to false and vice-versa, each time an accordion item is clicked. Then, we will create the animations using React Spring. The animations will have conditional styles that will only apply when the state is true.

import { React, useState } from "react";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";

function Accordion(props) {
  const [open, setOpen] = useState(false);
  //toggle accordion function
  let toggleHandler = (e) => {
    //switch state
    setOpen(!open);
  };

  return (
    <div className="accordion__item" >
      <div className="accordion__header" onClick={toggleHandler}>
        <h4 >{props.title}</h4>
        <i>
          <ExpandMoreIcon />
        </i>
      </div>
      <p className="accordion__content">{props.text}</p>
    </div>
  );
}

export default Accordion;

Now when we click the accordion, it will toggle the state. But visually, nothing will happen. For this, we need to add the Spring Animations.

Spring Animations

Now we will add the animations using React Spring. Install React Spring with the following command.

npm install react-spring

To add the animations, firstly import the useSpring hook. Next, we will create two different animations—one for the opening the accordion and the other for rotating the icon. To link the animations to the corresponding element, we will use the style property.

Note: We need to add animated before the element name in the tag.

import { React, useState } from "react";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import { useSpring, animated } from "react-spring";

function Accordion(props) {
  const [open, setOpen] = useState(false);
  //toggle accordion function
  let toggleHandler = (e) => {
    //switch state
    setOpen(!open);
  };

  //conditional styling
  const styles = {
    //if open is true, show content
    accordionTitle: {
      color: open ? "#10d6f5" : "#fff"
    }
  };
  //open animation with react spring

  const openAnimation = useSpring({
    from: { opacity: "0", maxHeight: "25px" },
    to: { opacity: "1", maxHeight: open ? "120px" : "25px" },
    config: { duration: "300" }
  });

  //rotate animation
  const iconAnimation = useSpring({
    from: {
      transform: "rotate(0deg)",
      color: "#ffff"
    },
    to: {
      transform: open ? "rotate(180deg)" : "rotate(0deg)",
      color: open ? "#10d6f5" : "#fff"
    },
    config: { duration: "120" }
  });

  return (
    <animated.div className="accordion__item" style={openAnimation}>
      <div className="accordion__header" onClick={toggleHandler}>
        <h4 style={styles.accordionTitle}>{props.title}</h4>
        <animated.i style={iconAnimation}>
          <ExpandMoreIcon />
        </animated.i>
      </div>
      <p className="accordion__content">{props.text}</p>
    </animated.div>
  );
}

export default Accordion;

Let's look at the above code step-by-step.

  1. Firstly, after importing useSpring, we are create a styles object. This is for changing the color of title if the accordion is open.
  2. Next, we have created the open animation that will increase the height of the accordion item to show the text if it is clicked. The opacity is to create a nice fade effect when the page loads. It is not necessary. The duration prop is self explanatory.
  3. The next animation is for the icon. When the accordion is opened, the icon will rotate and the color will change to blue.

Page Title Animation

This part is completely optional.

Basically, we will create a bounce animation for the page title once the page loads. Like before we will create a spring animation and add it to the h1 and also change the tag name to <animated.h1>.

You can play around with the mass, tension and friction properties to create more bounce, etc.

Your App.js will look like this.

App.js

import React from "react";
import "./app.css";
import Accordion from "./Components/Accordion";
import { useSpring, animated } from "react-spring";

function App() {
  //title animation
  const titleAnimation = useSpring({
    from: {
      transform: "translateY(-30px)"
    },
    to: [{ transform: "translateY(15px)" }],
    config: { mass: 3, tension: 500, friction: 25 }
  });

  return (
    <div className="main">
      <animated.h1 style={titleAnimation}>React Accordion</animated.h1>
      <div className="accordion">
        <Accordion
          title="Item 1 - Lorem ipsum dolor sit amet"
          text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam"
        />
        <Accordion
          title="Item 2 - Lorem ipsum dolor sit amet"
          text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam"
        />
        <Accordion
          title="Item 3 - Lorem ipsum dolor sit amet"
          text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam"
        />
        <Accordion
          title="Item 4 - Lorem ipsum dolor sit amet"
          text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam"
        />
      </div>
    </div>
  );
}

export default App;

And we are done!

Your working accordion will be looking like this now.

Working Accordion

Working Accordion

Explore Other Ways Too!

So there we have it. A simple animated accordion in React JS. There are many other ways of achieving this, so you can explore!

Thanks for reading!

This content is accurate and true to the best of the author’s knowledge and is not meant to substitute for formal and individualized advice from a qualified professional.