How to Build a Responsive Accordion/Collapsibles Component Purely using TailwindCSS

How to Build a Responsive Accordion/Collapsibles Component Purely using TailwindCSS

In web design, an accordion is a type of menu that displays a list of headers stacked on top of one another. When clicked on (or triggered by a keyboard interaction or screen reader), these headers will either reveal or hide associated content.

This design pattern is ideal for breaking down long-form or complex content into digestible chunks. It’s also ideal for mobile sites since it reduces how much a user has to scroll. This kind of component is commonly used on a FAQ page of a website.

This gives people control over what to read, and when, which can enhance their user experience.

In this Section, we will be building one of these amazing components purely using TailwindCSS.

Understanding the task

The design of an accordion varies by site and purpose, its user interface is usually made up of three elements.

  • Header

  • The icon

  • Accordion Content (Panel)

We will be discussing each part while building our design.

Structure of Code

Our code structure for this exercise is similar to the other tutorial we have been doing, as follows;

<body>
<!-- First Layer -->
  <div>
<!-- Second Layer -->
      <div>
            <!-- 
                Accordion Content     
             -->

      </div>
  </div>
</body>

Throughout this task, we will be focusing on one particular accordion, and we will replicate it for other parts

Structure of Accordion

<div class="m-[0.8rem] overflow-hidden border-b border-red-400 shadow-lg">
 <input type="checkbox" name="faq_1" id="faq_1" class="sr-only peer">
 <label for="faq_1" class="peer-checked:[&>section]:text-white peer-checked:[&>section]:bg-[rgb(225,29,72,1)] peer-checked:[&>section>div>h2]:hidden  peer-checked:[&>section>div>h3]:block peer-checked:[&>div]:max-h-screen peer-checked:[&>div]:p-[1rem]">
                <!-- Header-->
 <section class="p-[1em] cursor-pointer font-bold flex justify-between text-slate-500">
     <h2 class="w-[80%]">What is an Accordion?</h2>
                <!-- Icons-->
      <div class="text-xl flex items-center justify-center">
          <h2 class="block">&plus;</h2>
          <h3 class="hidden">&minus;</h3>
       </div>
</section>
                <!-- Accordion Content (Panel) -->
  <div class="max-h-0 p-[0.001rem] bg-white transition-all duration-[1s] text-[0.8rem]">
   <p>
  Accordion is a graphical control element comprising a vertically stacked list of items, such as labels and thumbnails. 
 An accordion is similar in purpose to a tabbed interface, a list of items where exactly one item is expanded into a panel
  </p>
  <div class="w-fit px-4 py-2 border text-xs mt-2 border-slate-800 rounded-full cursor-pointer active:scale-95 hover:bg-slate-800 hover:text-white transition-all duration-200">
          <h2>Read More</h2>
  </div>
</div>
</label>
</div>

Let's understand the code we just wrote. we will discuss the different parts first, then we will talk about how we made this functional.

Header

Principally our header just contains a text whose width is w-[80%], that's 80% of the parent container. It is important to emphasize that its parent container is a flex container containing both the header and the icons.

<h2 class="w-[80%]">What is an Accordion?</h2>

Icons

Here, to avoid imports or adding SVG files, we just used ASCII values to add "+" and "−" which serve the purpose of our task.

        <!-- Icons-->
<div class="text-xl flex items-center justify-center">
    <h2 class="block">&plus;</h2>
    <h3 class="hidden">&minus;</h3>
</div>

Accordion Content (Panel)

Here to now much styling was done.

                <!-- Accordion Content (Panel) -->
  <div class="max-h-0 p-[0.001rem] bg-white transition-all duration-[1s] text-[0.8rem]">
   <p></p>
  <div class="w-fit px-4 py-2 border text-xs mt-2 border-slate-800 rounded-full cursor-pointer active:scale-95 hover:bg-slate-800 hover:text-white transition-all duration-200">
          <h2>Read More</h2>
  </div>
</div>

To the container, we gave a max-height of max-h-0

Please note this max-h-0 carefully as we will need this particular property soon

For the Read More button, it is just routine styles like padding-inline of px-4 and padding-block of py, hover effects on background-color and text using hover:bg-slate-800 hover:text-white

This is basically the structure of an accordion.

Now! How do we make it functional?

We achieve this with the help of two things, an input checkbox and a label.

  • We grab all of our accordions into the labels, and we use the state of the checkbox to alter the characteristics of other properties.
<input type="checkbox" name="faq_1" id="faq_1" class="sr-only peer">
 <label for="faq_1" class="peer-checked:[&>section]:text-white peer-checked:[&>section]:bg-[rgb(225,29,72,1)] peer-checked:[&>section>div>h2]:hidden  peer-checked:[&>section>div>h3]:block peer-checked:[&>div]:max-h-screen peer-checked:[&>div]:p-[1rem]">

For the first accordion, we gave it a name="faq_1" and id="faq_1". it is important to also give the properties sr-only and peer to the input field.

Peer class adds functionality to a website in HTML. It's almost like JS where things work using an input radio. It depends on what the value of the input is set to. But in this situation, we are using a checkbox as we want to be able to open different sections of the accordion at the same time.

While Screen-reader-only elements (sr-only) hide an element visually without hiding it from screen readers:

I believe these two classes make a lot more sense now.

We made use of peer-checked to alter different properties within the label component. For example, peer-checked:[&>section]:text-white peer-checked:[&>section]:bg-[rgb(225,29,72,1)], simply means, if the checkbox is checked, change the text color of the section part to text-white, and also background-color to bg-[rgb(225,29,72,1)]

The same idea goes for all the others.

It is worth noting that, you can not change properties that weren't initially defined. For example, You can challenge the background-color of the section part if the section part didn't have bg-white.

This logic was also used to make the Accordion content visible or not. Initially, its max-height is max-h-0, when the checkbox is checked, this max-height changes to max-h-screen. If max-h-0 was not defined or was named something else like min-h-0 or just h-0, the peer-checked won't work.

And that's basically how you can build an accordion using TailwindCSS.

Of Course, this was just one of the 5 accordions, this is how the whole code looks like,

<div class="[&>*]:mb-5">
  <div class="m-[0.8rem] overflow-hidden border-b border-red-400 shadow-lg">
   <input type="checkbox" name="faq_1" id="faq_1" class="sr-only peer">
   <label for="faq_1" class="peer-checked:[&>section]:text-white peer-checked:[&>section]:bg-[rgb(225,29,72,1)] peer-checked:[&>section>div>h2]:hidden  peer-checked:[&>section>div>h3]:block peer-checked:[&>div]:max-h-screen peer-checked:[&>div]:p-[1rem]">
   <section class="p-[1em] cursor-pointer font-bold flex justify-between text-slate-500">
     <h2 class="w-[80%]">What is an Accordion?</h2>
      <div class="text-xl flex items-center justify-center">
              <h2 class="block">&plus;</h2>
              <h3 class="hidden">&minus;</h3>
       </div>
  </section>

   <div class="max-h-0 p-[0.001rem] bg-white transition-all duration-[1s] text-[0.8rem]">
    <p>
    Accordion is a graphical control element comprising a vertically stacked list of items, such as labels and thumbnails. 
    An accordion is similar in purpose to a tabbed interface, a list of items where exactly one item is expanded into a panel
    </p>
    <div class="w-fit px-4 py-2 border text-xs mt-2 border-slate-800 rounded-full cursor-pointer active:scale-95 hover:bg-slate-800 hover:text-white transition-all duration-200">
         <h2>Read More</h2>
     </div>
  </div>
 </label>
</div>


<div class="m-[0.8rem] overflow-hidden border-b border-red-400  shadow-lg">
   <input type="checkbox" name="faq_2" id="faq_2" class="sr-only peer">
   <label for="faq_2" class="peer-checked:[&>section]:text-white peer-checked:[&>section]:bg-[rgb(225,29,72,1)] peer-checked:[&>section>div>h2]:hidden  peer-checked:[&>section>div>h3]:block peer-checked:[&>div]:max-h-screen peer-checked:[&>div]:p-[1rem]">
    <section class="p-[1em] cursor-pointer font-bold flex justify-between text-slate-500">
        <h2 class="w-[80%]">When and how it should be used?</h2>
    <div class="text-xl flex items-center justify-center">
              <h2 class="block">&plus;</h2>
              <h3 class="hidden">&minus;</h3>
     </div>
   </section>

   <div class="max-h-0 p-[0.001rem] bg-white transition-all duration-[1s] text-[0.8rem]">
      <p>
       Accordion is a graphical control element comprising a vertically stacked list of items, such as labels and thumbnails. 
       An accordion is similar in purpose to a tabbed interface, a list of items where exactly one item is expanded into a panel
       </p>
       <div class="w-fit px-4 py-2 border text-xs mt-2 border-slate-800 rounded-full cursor-pointer active:scale-95 hover:bg-slate-800 hover:text-white transition-all duration-200">
              <h2>Read More</h2>
       </div>
     </div>
   </label>
</div>

 <div class="m-[0.8rem] overflow-hidden border-b border-red-400  shadow-lg">
     <input type="checkbox" name="faq_3" id="faq_3" class="sr-only peer">
     <label for="faq_3" class="peer-checked:[&>section]:text-white peer-checked:[&>section]:bg-[rgb(225,29,72,1)] peer-checked:[&>section>div>h2]:hidden  peer-checked:[&>section>div>h3]:block peer-checked:[&>div]:max-h-screen peer-checked:[&>div]:p-[1rem]">
       <section class="p-[1em] cursor-pointer font-bold flex justify-between text-slate-500">
         <h2 class="w-[80%]">What if the user clicks on a collapsed card while another card is open?</h2>
        <div class="text-xl flex items-center justify-center">
                 <h2 class="block">&plus;</h2>
                 <h3 class="hidden">&minus;</h3>
          </div>
      </section>

 <div class="max-h-0 p-[0.001rem] bg-white transition-all duration-[1s] text-[0.8rem]">
          <p>
            Accordion is a graphical control element comprising a vertically stacked list of items, such as labels and thumbnails. 
            An accordion is similar in purpose to a tabbed interface, a list of items where exactly one item is expanded into a panel
          </p>
         <div class="w-fit px-4 py-2 border text-xs mt-2 border-slate-800 rounded-full cursor-pointer active:scale-95 hover:bg-slate-800 hover:text-white transition-all duration-200">
               <h2>Read More</h2>
           </div>
        </div>
     </label>
 </div>

<div class="m-[0.8rem] overflow-hidden border-b border-red-400  shadow-lg">
      <input type="checkbox" name="faq_4" id="faq_4" class="sr-only peer">
      <label for="faq_4" class="peer-checked:[&>section]:text-white peer-checked:[&>section]:bg-[rgb(225,29,72,1)] peer-checked:[&>section>div>h2]:hidden  peer-checked:[&>section>div>h3]:block peer-checked:[&>div]:max-h-screen peer-checked:[&>div]:p-[1rem]">
   <section class="p-[1em] cursor-pointer font-bold flex justify-between text-slate-500">
        <h2 class="w-[80%]">How to choose an icon to indicate expansion?</h2>
     <div class="text-xl flex items-center justify-center">
           <h2 class="block">&plus;</h2>
           <h3 class="hidden">&minus;</h3>
      </div>
   </section>

   <div class="max-h-0 p-[0.001rem] bg-white transition-all duration-[1s] text-[0.8rem]">
      <p>
         Accordion is a graphical control element comprising a vertically stacked list of items, such as labels and thumbnails. 
          An accordion is similar in purpose to a tabbed interface, a list of items where exactly one item is expanded into a panel
      </p>
       <div class="w-fit px-4 py-2 border text-xs mt-2 border-slate-800 rounded-full cursor-pointer active:scale-95 hover:bg-slate-800 hover:text-white transition-all duration-200">
           <h2>Read More</h2>
        </div>
       </div>
   </label>
</div>
</div>

We obviously added some styling to the different layers of the different and to the body in order to achieve the end product as thus,

<body class="bg-slate-200 flex items-center justify-center min-h-screen">
<!-- First Layer -->
  <div class="p-4 flex items-center justify-center">
<!-- Second Layer -->
      <div class="relative w-full sm:max-w-lg bg-white rounded-lg p-5 sm:p-10">
        <div class="absolute -top-10 left-[10%] sm:-left-10 -z-10 ">
           <div class="w-[10rem] h-[10rem] sm:w-[15rem] sm:h-[15rem] bg-rose-300/50 rounded-full relative after:absolute after:content-[''] after:w-full after:h-full after:bg-pink-300/50 after:rounded-full after:-right-24"></div>
            </div>


            <!-- Accordion Content -->
                <div></div> 


     <div class="absolute -bottom-[0.9rem] right-1/2 sm:-right-8 -z-20">
  <div class="w-[15rem] h-[15rem] bg-rose-300/50 rounded-full relative after:absolute after:content-[''] after:w-[80%] after:h-[80%] after:bg-pink-300/50 after:rounded-full after:-bottom-12 after:-right-8"></div>
  </div>  


      </div>
  </div>
</body>

And that's pretty much all about it.

Conclusion

We just built a fully functional Accordion Component and in the process, we also had more insight about Tailwindcss.

Many employers will need such components to be added to their websites, and for sure you know how simple it is to create it straight from your HTML document.

You can have a Live preview on Codepen or find the code on GitHub

Don’t hesitate to share with me if you were able to complete the tutorial on your end, I’d be happy to see any additional components.

If you have any worries or suggestions, don’t hesitate to bring them up! 😊

See ya! 👋