How to create an Accordion

Accordion

The theme for week #13 of the Weekly Coding Challenge is:

Accordion

Hide and show content with just a click - this is what an accordion let us do. 😃

In this article we're going to build this Accordion:

https://codepen.io/FlorinPop17/pen/PvvZmN/

The HTML

For the HTML structure we'll use an ul with a few li's (or the accordion-items) containing the header (h3) and the content (p) with some dummy lorem text:

<ul class="accordion">
    <li class="accordion-item open">
        <h3>First accordion item</h3>
        <p>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet,
            provident.
        </p>
    </li>
    <li class="accordion-item">
        <h3>Second accordion item</h3>
        <p>
            Lorem ipsum dolor sit, amet consectetur adipisicing elit. Ex autem
            praesentium vitae dolores est eius officia aspernatur vero
            recusandae tempora!
        </p>
    </li>
    <li class="accordion-item">
        <h3>Third accordion item</h3>
        <p>
            Lorem ipsum dolor sit, amet consectetur adipisicing elit. Omnis
            asperiores officia cupiditate, officiis vel aliquid eum quidem,
            nostrum nihil hic repellendus dolorem facilis consequatur doloribus.
        </p>
    </li>
    <li class="accordion-item">
        <h3>Forth accordion item</h3>
        <p>
            Lorem ipsum dolor sit amet.
        </p>
    </li>
    <li class="accordion-item">
        <h3>Fifth accordion item</h3>
        <p>
            Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores
            saepe, pariatur earum sunt fugit reprehenderit eum provident
            accusantium eos perspiciatis deserunt sed voluptates autem cumque
            natus vel non nemo tenetur, perferendis repellat. Dolore eaque sed
            rerum alias. Necessitatibus illo, saepe voluptate, modi dolorum
            voluptates rem aspernatur, ipsum alias libero facere.
        </p>
    </li>
</ul>

As you can see, by default the first .accordion-item is .opened. You'll see in a moment what this does in the CSS. 🙂

The CSS

First, let's style the .accordion and its items:

.accordion {
    border-radius: 4px;
    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
    list-style-type: none;
    padding: 0;
    overflow: hidden;
}

.accordion-item {
    background-color: #fff;
    cursor: pointer;
    width: 400px;
}

This will create a fixed width accordion of 400px.

Next, let's style the header:

.accordion-item h3 {
    color: #fff;
    font-weight: 400;
    letter-spacing: 0.4px;
    margin: 0;
    padding: 20px 15px;
    position: relative;
}

As you can see, it has a relative position and this is because we want to add a small down pointing arrow within it using the ::after selector and a fontawesome icon:

.accordion-item h3::after {
    content: '\f078';
    font-family: 'Font Awesome 5 Free';
    font-weight: bold;
    position: absolute;
    top: 50%;
    right: 15px;
    transform: translateY(-50%) rotate(0);
    transition: transform 0.3s ease-in-out;
}

.accordion-item.open h3::after {
    transform: translateY(-50%) rotate(180deg);
}

We need to specify the font-family property and the desired icon (\f078 in our case) in order for it to show up. Also, let's rotate the icon 180deg when the accordion item is .opened.

Great! Next, we'll add the "gradient-like" effect on the accordion-items. For this we are going to target each separate item and apply a different background-color:

.accordion-item:nth-child(1) h3 {
    background-color: #fd79a8;
}

.accordion-item:nth-child(2) h3 {
    background-color: #f76ba2;
}

.accordion-item:nth-child(3) h3 {
    background-color: #f25e9d;
}

.accordion-item:nth-child(4) h3 {
    background-color: #ed5098;
}

.accordion-item:nth-child(5) h3 {
    background-color: #e84393;
}

Kind of old fashion as we could do it more dynamically, but for now it should do the job! (Note that if you have more than 5 items, you need to color them individually 😅).

Next, let's style the content (or the p in our case):

.accordion-item p {
    display: none;
    letter-spacing: 1px;
    margin: 0;
    padding: 15px;
    text-align: justify;
}

.accordion-item.open p {
    display: block;
}

As you can see the text is only displayed when the accordion is .opened.

I've chose to use just a simple p tag in this case, but you can add here multiple tags and contents and even create a multiple level accordion if you want. 😃

The JavaScript

And at the end, let's add a little bit of functionality.

For that we need to target all the .accordion-items and we'll add a click eventListener: Every time one item is clicked we'll do the following:

  • Check if the corresponding item is already opened by checking if it has the .open class:

    • if it is, close it by removing that class
    • if it isn't, remove the .open class from all the accordion_items and add it only to the clicked one
const accordion_items = document.querySelectorAll('.accordion-item');

accordion_items.forEach(elem =>
    elem.addEventListener('click', () => {
        if (elem.classList.contains('open')) {
            elem.classList.remove('open');
        } else {
            accordion_items.forEach(elem2 => elem2.classList.remove('open'));
            elem.classList.add('open');
        }
    })
);

Conclusion

You can go one step further and add a little bit of animation when the .accordion-item is closed and opened.

I'm very curious to see what other functionalities you'll add to this simple component! Have fun! 😄

Happy Coding! 😇

Tagged with html5, css3, javascript, transform, after, accordion, weekly-coding-challenge