Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

245
Views
Make accordion item open by default

In my accordion set I'm trying to get the first accordion item open by default on page load.

I'm adding the class .open to that element, like such:

<button class="open">

This seems to work but the problem is when I click on that same element instead of closing it, it keeps re-opening it and by looking at the JS script I don't quite understand what could be the problem.

Demo

var accordionButton = document.querySelectorAll("button");

for (var i = 0; i < accordionButton.length; i++) {
  accordionButton[i].addEventListener("click", switchClasses);
}

function switchClasses() {
  for (var i = 0; i < accordionButton.length; i++) {
    if (this !== accordionButton[i]) {
      accordionButton[i].classList.remove("open");
      accordionButton[i].nextElementSibling.style.maxHeight = null;
    }
  }
  this.classList.toggle("open");
  var nextAccordionButton = this.nextElementSibling;
  if (nextAccordionButton.style.maxHeight) {
    nextAccordionButton.style.maxHeight = null;
  } else {
    nextAccordionButton.style.maxHeight =
      nextAccordionButton.scrollHeight + "px";
  }
}
.accordion-item {
  border: 1px solid lightgrey;
}

button {
  background: none;
  border: none;
  width: 100%;
  max-width: none;
  height: auto;
  padding: 12px;
  text-align: left;
  cursor: pointer;
  transition: 0.5s;
}

.content-wrapper {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}

.content {
  padding: 0 10px;
}

.open {
  background: lightgray;
  border-bottom: none;
}

.open + .content-wrapper {
  max-height: none;
}
<div class="accordion-item">
  <button class="open">
    <span class="accordion__title">Accordion 1</span>
  </button>
  <div class="content-wrapper">
    <div class="content">
      <p>Accordion 1 content.
    </div>
  </div>
</div>
<div class="accordion-item">
  <button>
    <span class="accordion__title">Accordion 2</span>
  </button>
  <div class="content-wrapper">
    <div class="content">
      <p>Accordion 2 content.
    </div>
  </div>
</div>
<div class="accordion-item">
  <button>
    <span class="accordion__title">Accordion 3</span>
  </button>
  <div class="content-wrapper">
    <div class="content">
      <p>Accordion 3 content.
    </div>
  </div>
</div>

almost 4 years ago · Santiago Trujillo
2 answers
Answer question

0

You also have to check for the currently clicked element. What happened was that you were constantly re-applying open to the element right after removing it.

Also, try to use const for variables that wont be re-assigned. and let for variables that will be mutated. var keyword is not advised.

const accordionButton = document.querySelectorAll('button');

for (let i = 0; i < accordionButton.length; i++) {
  accordionButton[i].addEventListener('click', switchClasses);
}

function switchClasses() {
  for (let i = 0; i < accordionButton.length; i++) {
    if (this !== accordionButton[i]) {
      accordionButton[i].classList.remove('open');
      accordionButton[i].nextElementSibling.style.maxHeight = null;
      continue;
    }

    if (this === accordionButton[i]) {
      if (!this.classList.contains('open')) {
        this.classList.add('open');
        const nextAccordionButton = this.nextElementSibling;
        nextAccordionButton.style.maxHeight =
          nextAccordionButton.scrollHeight + 'px';
      } else {
        accordionButton[i].classList.remove('open');
        accordionButton[i].nextElementSibling.style.maxHeight = null;
      }
    }
  }
}
.accordion-item {
  border: 1px solid lightgrey;
}

button {
  background: none;
  border: none;
  width: 100%;
  max-width: none;
  height: auto;
  padding: 12px;
  text-align: left;
  cursor: pointer;
  transition: 0.5s;
}

.content-wrapper {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}

.content {
  padding: 0 10px;
}

.open {
  background: lightgray;
  border-bottom: none;
}

.open+.content-wrapper {
  max-height: none;
}
<div class="accordion-item">
  <button class="open">
    <span class="accordion__title">Accordion 1</span>
  </button>
  <div class="content-wrapper">
    <div class="content">
      <p>Accordion 1 content.</p>
    </div>
  </div>
</div>
<div class="accordion-item">
  <button>
    <span class="accordion__title">Accordion 2</span>
  </button>
  <div class="content-wrapper">
    <div class="content">
      <p>Accordion 2 content.</p>
    </div>
  </div>
</div>
<div class="accordion-item">
  <button>
    <span class="accordion__title">Accordion 3</span>
  </button>
  <div class="content-wrapper">
    <div class="content">
      <p>Accordion 3 content.</p>
    </div>
  </div>
</div>

almost 4 years ago · Santiago Trujillo Report

0

Here is a simple accordion example to simplify your problem/structure. On click, I remove open if the clicked element has the class. Else, I remove the class if an accordion is opened, then I open the clicked accordion.

document.querySelectorAll("button").forEach((e) => {
  e.addEventListener("click", () => {
    if (e.classList.contains("open")) {
      e.classList.remove("open")
    } else {
      let opened = document.querySelector("button.open")
      if (opened) {
        opened.classList.remove("open")
      }
      e.classList.add("open")
    }
  })
});
.content {
  display: none;
}

button {
  display: block;
}

.open {
  background-color: orange;
}

.open+.content {
  display: block;
}
<button class="open">Accordion 1</button>
<div class="content">Content 1</div>
<button>Accordion 2</button>
<div class="content">Content 2</div>
<button>Accordion 3</button>
<div class="content">Content 3</div>

Also if you want to allow multiple accordions opened at the same time, you can make it only with HTML and CSS using checkboxes.

input {
  display: none;
}

label {
  display: block;
  width: fit-content;
}

input:checked+label {
  background-color: orange;
}

.content {
  display: none;
}

input:checked+label+.content {
  display: block;
}
<input type="checkbox" id="accordion-1" checked/>
<label class="btn" for="accordion-1">Accordion 1</label>
<div class="content">Content 1</div>
<input type="checkbox" id="accordion-2" />
<label class="btn" for="accordion-2">Accordion 2</label>
<div class="content">Content 2</div>
<input type="checkbox" id="accordion-3" />
<label class="btn" for="accordion-3">Accordion 3</label>
<div class="content">Content 3</div>

almost 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!