How to Make an Accordion FAQ with JS - part 3
Adding JavaScript to rotate a button when it's clicked
In the final step of building our accordion FAQ, we'll add styling to our FAQ project and make it a little easier on the eyes. We'll also have the double chevron to rotate to indicate the direction of movement. Currently, our SCSS looks like this:
.answer {
display: none;
}
.clicked {
.answer {
display: block;
}
}
It's pretty boring, so let's get to work!
SCSS
Inside our body
we're going to have our main
that will have a class
of container
. I set the width
to 80vw as I like to set an element's size based on the view's screen size versus a hard number in pixels. The margins
are set to auto to keep the container centered save for the top, it's 50px, so the container is dropped down from the top of the screen a bit. Here's the code I ended up with:
.container {
width: 80vw;
border-radius: 5px;
padding: 15px;
margin: 50px auto auto auto;
}
As I mentioned in part 1, the questions themselves are article
s, and will be given a class
of q
, and the article
s will contain a div .title
, h2
that's the question, our button
, a second div
with .answer
and it will hold a p
with the answer to the question.
To keep the code DRY I put some default styles on div
like so:
div {
display: flex;
margin-left: auto;
margin-right: auto;
justify-content: center;
align-items: center;
}
.q
has aborder-radius
of 5px to soften the corners, and I added a box-shadow
to give it some depth. To keep my code cleaner I used a variable to add shadows (just one of the great things about Sass/SCSS!); in this instance it's $boxshadow: 0 14px 12px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
, so my .q
looks like:
.q {
width: 100%;
background-color: lavender;
color: $purple; //variable for #732091
border-radius: 5px;
padding-top: 3px;
margin: 5px 5px 17px 5px; //bottom margin is larger to accomodate the box-shadow
font-size: 25px;
font-weight: 600;
box-shadow: $boxshadow;
}
Inside .q
I nested the h2
that will be used to hold the question. Notice the margin
set to auto to keep the button
to the right.
h2 {
padding: 7px;
font-size: 23px;
margin: auto;
}
The button
s are next, I gave them a margin-right
of 10px to nudge them in a little and transition: transform .5s ease-in-out
to soften the transitions between movements. Here's the final result:
button {
cursor: pointer;
background-color: rgba(255,255,255,0); //removes the background color
border: 0px;
padding: 1px 7px;
color: $purple;
font-size: 25px;
font-weight: 600;
margin-right: 10px;
text-align: center;
transition: transform .5s ease-in-out;
}
I gave my button
s all .qb
(for question button) so I could grab them with the JavaScript to add the rotation.
Nested in button
I have img
, which is what holds the double chevron. The image I used is larger than what I need, so I set the height
and let the width
figure itself out:
img {
height: 25px;
width: auto;
}
You may not need to do this, it'll depend on the image you select.
Now let's move on to .answer
. The most important thing to have is what we set up in part 1: display: none
so the answers aren't visible. Everything else is just preferences.
.answer {
display: none;
padding: 13px;
background-color: lavender;
font-weight: 300;
font-size: 18px;
border-radius: 5px;
}
Last is a class
that will be added or removed via onClick
that will turn the chevron.
.rotate {
transform: rotate(180deg);
}
Our SCSS is looking pretty good! Now it's time to finish up the JavaScript.
JavsScriptmobile
We need to get access to the chevrons to turn them: we need to add const arrow=quest.querySelector('.qb');
to our JavaScript inside forEach
. Next, we'll jump a few lines down into addEventListener
where we can toggle the rotate
class we just made on arrow
like so: arrow.classList.toggle('rotate');
. We're using toggle
because it's perfect in this situation: if the .rotate
isn't present, it's added, otherwise it's removed. Let's take a look at our project:
If you've made it this far, congrats! You made an accessible accordion FAQ using HTML, SCSS and JavaScript!
Here's the complete code used in this three part tutorial:
HTML
<main class="container">
<h1>Frequently Asked Questions</h1>
<article class="q" aria-expanded="false">
<div class="title">
<h2>What's the difference between a hippo and a zippo?</h2>
<button class="qb" aria-label="toggle answer">
<img src="https://i.ibb.co/KKmX2q3/chevron.png" alt="chevron" />
</button>
</div>
<div class="answer">
<p>One is really heavy, the other is a little lighter.</p>
</div>
</article>
</main>
SCSS
$boxshadow: 0 14px 12px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
$purple: #732091;
.container {
width: 80vw;
border-radius: 5px;
padding: 15px;
margin: 50px auto auto auto;
}
div {
display: flex;
margin-left: auto;
margin-right: auto;
justify-content: center;
align-items: center;
}
.answer {
display: none;
}
.clicked {
.answer {
display: block;
}
}
.q {
width: 100%;
background-color: lavender;
color: $purple;
border-radius: 5px;
padding-top: 3px;
margin: 5px 5px 17px 5px;
font-size: 25px;
font-weight: 600;
box-shadow: $boxshadow;
.title {
width: 100%;
}
h2 {
padding: 7px;
font-size: 23px;
margin: auto;
}
}
button {
cursor: pointer;
background-color: rgba(255, 255, 255, 0);
border: 0px;
padding: 1px 7px;
color: $purple;
font-size: 25px;
font-weight: 600;
margin-right: 10px;
text-align: center;
transition: transform .5s ease-in-out;
img {
height: 25px;
width: auto;
}
}
.answer {
display: none;
padding: 13px;
background-color: lavender;
font-weight: 300;
font-size: 18px;
border-radius: 5px;
}
.rotate {
transform: rotate(180deg);
}
JavaScript
const question=document.querySelectorAll('.q');
question.forEach(function (quest) {
const btn=quest.querySelector('button');
let arrow=quest.querySelector('.qb');
btn.addEventListener('click', function() {
quest.classList.toggle('clicked');
arrow.classList.toggle('rotate');
let ariaValue=quest.getAttribute('aria-expanded');
ariaValue = (ariaValue === 'false' ? quest.setAttribute('aria-expanded', 'true') : quest.setAttribute('aria-expanded', 'false');
});
});
I added a few more styles to my finished project, feel free to adjust the styles to your taste. If you've made your own accordion FAQ, please leave a link in the comments! Let me know if you have any questions.