DEV Community

Bionic Julia
Bionic Julia

Posted on • Originally published at on


Creating a React Accordion Component Using Just CSS

About a year ago now, I wrote a blog post on how to create an accordion component in React with Typescript and TailwindCSS. I recently needed to implement an accordion component again (this is why keeping a blog is so handy!), but this time in a codebase that doesn’t use TailwindCSS. Here’s a short follow-on to that post for how you’d create an accordion component if you were just using straight CSS. I'd recommend reading that post first if you're new to React, as it includes more detail on the order in which I built up the code.

Note that I’ve left most of the styling of the overall component out and focused on the important ones that effect the transition.

import React, { MutableRefObject, useRef, useState } from 'react'
import { appConfig } from '../appConfig'

interface AccordionProps {
  title: React.ReactNode
  content: React.ReactNode

export const Accordion: React.FC<AccordionProps> = ({ title, content }) => {
  const [showExtraContent, setShowExtraContent] = useState(false)
  const [height, setHeight] = useState('0px')

  const contentSpace = useRef(null) as MutableRefObject<HTMLDivElement>

  function toggleAccordion() {
        setShowExtraContent((previousState) => !previousState)
    setHeight(showExtraContent ? '0px' : `${contentSpace.current.scrollHeight}px`)

  return (
    <div className="container">
          alt="Chevron icon"
          className={`${showExtraContent ? 'rotate' : null} arrow`}
        style={{ maxHeight: `${height}` }}
Enter fullscreen mode Exit fullscreen mode

Here are the corresponding CSS styles.

.container {
  display: flex;
  flex-direction: column;

.arrow {
  transition: 0.3s;

.rotate {
  transform: rotate(180deg);

.extra-content {
  overflow: hidden;
  transition: max-height 0.3s ease-in-out;
Enter fullscreen mode Exit fullscreen mode

Like this post? Read more from me at

Top comments (0)

11 Tips That Make You a Better Typescript Programmer

1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields


Read the whole post now!