Accordion in JavaScript – show / hide sections

Accordion in JavaScript – show / hide sections

Sometimes to display information properly you need to show / hide a block or hide part of the text (or any other content) in tabs and display it only when the user clicks a tab. Let's look at two ways to implement collapsible and expandable tabs – in short: how to build an accordion in JavaScript. Both approaches can use the same CSS:

html, body {
    height: 100%;
}

h2, div, p {
    margin: 0;
    padding: 0;
}

.tab {
    width: 100%;
    height: 10%;
    background-image: url(edge.png);
    background-repeat: repeat-x;
    border: 1px solid orange;
}
.tab:hover {
    background-color: #eee;
    cursor: pointer;
}
.tab h2 {
    padding: 10px 20px;
    background-color: orange;
}
.tab h2:hover {
    padding: 10px 20px;
    background-color: #eee;
}

.expanded {
    height: 45%;
    padding-bottom: 2%;
    border-right: 2px dashed orange;
    border-left: 2px dashed orange;
    border-bottom: 2px dashed orange;
}

.displayed {
    display: block;
    padding: 20px 10px;
}

.hidden {
    display: none;
}

Accordion Variant 1 – using onclick on tabs

In this version we attach the click handler directly to each tab via onclick to toggle the visibility:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css" href="edge.css">
</head>
<body>
    <div class="tab" id="0" onclick="expand(this.id);">
        <h2>Click me!</h2>
        <p class="hidden">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p>
    </div>
    <div class="tab" id="1" onclick="expand(this.id);">
        <h2>Click me!</h2>
        <p class="hidden">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p>
    </div>
    <div class="tab" id="2" onclick="expand(this.id);">
        <h2>Click me!</h2>
        <p class="hidden">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p>
    </div>
    <script>
        function expand (id) {
            var tabs = document.querySelectorAll("div.tab");
            var texts = document.querySelectorAll("div.tab>p");
            console.log(id);
            if (texts[id].className == "displayed") {
                texts[id].className = "hidden";
                tabs[id].classList.remove("expanded");
            } else {
                for (var i = 0; i < texts.length; i++) {
                    texts[i].className = "hidden";
                    tabs[i].classList.remove("expanded");
                }
                texts[id].className = "displayed";
                tabs[id].classList.add("expanded");
            }
        };
    </script>
</body>
</html>

Accordion Variant 2 – handling clicks inside the script

Visually the blocks appear and collapse the same way, but here we attach the click listeners programmatically within the script instead of using onclick attributes:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css" href="edge.css">
</head>
<body>
    <div class="tab" id="0">
        <h2>Click me!</h2>
        <p class="hidden">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p>
    </div>
    <div class="tab" id="1">
        <h2>Click me!</h2>
        <p class="hidden">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p>
    </div>
    <div class="tab" id="2">
        <h2>Click me!</h2>
        <p class="hidden">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.</p>
    </div>
    <script>
        var tabs = document.querySelectorAll("div.tab");
        var texts = document.querySelectorAll("div.tab>p");

        tabs[0].onclick = function () {
            if (texts[0].className == "displayed") {
                texts[0].className = "hidden";
                tabs[0].classList.remove("expanded");
            } else {
                for (var i = 0; i < texts.length; i++) {
                    texts[i].className = "hidden";
                    tabs[i].classList.remove("expanded");
                }
                texts[0].className = "displayed";
                tabs[0].classList.add("expanded");
            }
        };
        tabs[1].onclick = function () {
            if (texts[1].className == "displayed") {
                texts[1].className = "hidden";
                tabs[1].classList.remove("expanded");
            } else {
                for (var i = 0; i < texts.length; i++) {
                    texts[i].className = "hidden";
                    tabs[i].classList.remove("expanded");
                }
                texts[1].className = "displayed";
                tabs[1].classList.add("expanded");
            }
        };
        tabs[2].onclick = function () {
            if (texts[2].className == "displayed") {
                texts[2].className = "hidden";
                tabs[2].classList.remove("expanded");
            } else {
                for (var i = 0; i < texts.length; i++) {
                    texts[i].className = "hidden";
                    tabs[i].classList.remove("expanded");
                }
                texts[2].className = "displayed";
                tabs[2].classList.add("expanded");
            }
        };
    </script>
</body>
</html>

As you can see, creating a js accordion is pretty straightforward.