DEV Community

Cover image for Creating a FAQ accordion WITHOUT any Javascript!?
Mark Townsend
Mark Townsend

Posted on

Creating a FAQ accordion WITHOUT any Javascript!?

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
  ...
Enter fullscreen mode Exit fullscreen mode

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.

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

Latest comments (1)

Collapse
 
diomed profile image
May Kittens Devour Your Soul

Adding

duration-300 ease-out

to SVG class makes chevron icons rotate smoothlier and kinda enhaces it a bit