Creating a FAQ accordion WITHOUT any Javascript!?
Tags: tailwindcss, accordion, faq, toggle
Published: 2022-05-23 02:35:30

You've got a product or platform and you've anticipated the questions that are commonly asked. Time to build an FAQ (frequently asked questions) page to save you the time of answering the same questions repeatedly.

Did you know you don't even need to touch Javascript to make a beautiful accordion FAQ? Sounds crazy, right?! All we need is HTML and CSS. For this demonstration I'm going to be using Tailwind 3+ (because of its integration with JIT) to show you how easy it is. Let's get started!

_If you want the full source code skip to the bottom._

Let's start with the most basic markup:

    <section>
      <details>
        <summary>
          Question 1
        </summary>
        <p>Answer 1.</p>
      </details>

      <details>
        <summary>
          Question 2
        </summary>
        <p>Answer 2.</p>
      </details>

      <details>
        <summary>
          Question 3
        </summary>
        <p>Answer 3.</p>
      </details>
    </section>

The `details` tag automatically gives us the ability to show and hide content outside of the summary by default. It's where all the magic happens that allows us to completely skip using any Javascript.

The first thing we want to do is get rid of the browser's basic arrow character so we can style everything ourselves. Tailwind has a handy pseudo element selector called `marker:` which lets us style this. You may think that `marker:hidden` would do the trick to get rid of those pesky arrows, but surprisingly, it doesn't! However, because the browser treats them as inline text we can simply make them disappear by setting their font size to 0. Adding the following onto each `<summary>` tag will do the trick: `class="marker:[font-size:0px]"`

    <section>
      <details>
        <summary class="marker:[font-size:0px]">
          Question 1
        </summary>
        <p>Answer 1.</p>
      </details>

      <details>
        <summary class="marker:[font-size:0px]">
          Question 2
        </summary>
        <p>Answer 2.</p>
      </details>

      <details>
        <summary class="marker:[font-size:0px]">
          Question 3
        </summary>
        <p>Answer 3.</p>
      </details>
    </section>

Now that we got rid of those ugly arrows we can add our own. Let's make the summary a flex box and add svgs so we can make it look better.

    <details>
    <summary class="flex flex-row items-center justify-between marker:[font-size:0px]">
      Question 1
      <svg class="h-6 w-6 rotate-0 transform text-gray-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true">
        <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"></path>
      </svg>
      </summary>
      <p>Answer 1.</p>
    </details>

Awesome! We've got our nice arrow now. Looks a lot better. But immediately you'll notice a problem. It doesn't rotate when we open it to show that the content has been expanded.

If you click on the summary tag you'll notice an html attribute of `open` being added. We can target this with CSS to apply css to the svg and make it transform and rotate accordingly. To do this, we're going to have to apply Tailwind's `group` class on the `details` element so we can make the svg react when it changes. We'll add a class of `group-open:rotate-180` to the svg itself.

    <details class="group">
    <summary class="flex flex-row items-center justify-between marker:[font-size:0px]">
      Question 1
      <svg class="h-6 w-6 rotate-0 transform text-gray-400 group-open:rotate-180" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true">
        <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"></path>
      </svg>
      </summary>
      <p>Answer 1.</p>
    </details>

It's really starting to come together now and we still haven't needed Javascript. Let's add a little polish with colors, font size, padding and make the cursor change to a pointer on hover.

    <section class="grid grid-cols-1 gap-y-3 divide-y">
      <details open class="group py-1 text-lg">
        <summary class="flex cursor-pointer flex-row items-center justify-between py-1 font-semibold text-gray-800 marker:[font-size:0px]">
          Question 1
          <svg class="h-6 w-6 rotate-0 transform text-gray-400 group-open:rotate-180" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true">
            <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"></path>
          </svg>
        </summary>
        <p class="text-gray-500">Answer 1.</p>
      </details>
      ...
  </section>

That's looking `really` close to finished. You can just add your personal touches and it's ready to answer all those questions you don't have time to respond to!

One final thing to know about this is if you add an `open` attribute onto the `<details>` tag it will automatically be expanded on page load. You can use this with a snippet of Javascript or to simply have the first item already opened for the visitor. If you need to apply any more styling to the `<summary>` tag when it is expanded, just use the `marker:` pseudo selector in Tailwind.

### You can view the full source code at [this Tailwind Playground](https://play.tailwindcss.com/I9nwaTQdoX).

If you liked this article, please give it a like or share it on Twitter!