DEV Community

joachim kliemann
joachim kliemann

Posted on • Updated on

Creating an Accordion with CSS and a sprinkle of JavaScript

Creating a simple, CSS-only accordion with the details and summary HTML elements is not only efficient but also makes for a clean, manageable, and accessible UI component. Below, I will outline how to create a CSS-only accordion and then how to enhance it using JavaScript to ensure only one accordion item is open at a time. But before I will give you some basic information about the <details> tag

Structure
Here is the typical structure for the <details> element:

<details>
  <summary>Summary or Label</summary>
  Hidden content or detailed information goes here.
</details>
Enter fullscreen mode Exit fullscreen mode

Open Attribute
The open attribute is a boolean attribute that, when present, will make the <details> element start in the open state, meaning the hidden content is revealed by default. Here is an example:

<details open>
  <summary>Summary or Label</summary>
  This content is visible by default because of the open attribute.
</details>
Enter fullscreen mode Exit fullscreen mode

Interactivity
If you want to toggle the open attribute dynamically, you can do so using JavaScript by selecting the <details> element and manipulating its open property.

Accessibility
When using the <details> and <summary> tags, it's essential to consider accessibility. These elements are natively accessible to keyboard and screen reader users, meaning they can be navigated and activated using keyboard controls, and screen reader users will be informed about the expandable/collapsible nature of the element. However, always ensure to test with actual devices and users to confirm accessibility in real-world usage.

Accordion

HTML:
Use the <details> tag to create the accordion, and the <summary> tag to define the clickable title.

<details class="accordion-item" open>
  <summary class="accordion-header">Accordion Item 1</summary>
  <div class="accordion-content">
    Content for item 1 goes here...
  </div>
</details>

<details class="accordion-item">
  <summary class="accordion-header">Accordion Item 2</summary>
  <div class="accordion-content">
    Content for item 2 goes here...
  </div>
</details>

<details class="accordion-item">
  <summary class="accordion-header">Accordion Item 3</summary>
  <div class="accordion-content">
    Content for item 3 goes here...
  </div>
</details>

<details class="accordion-item">
  <summary class="accordion-header">Accordion Item 4</summary>
  <div class="accordion-content">
    Content for item 4 goes here...
  </div>
</details>
Enter fullscreen mode Exit fullscreen mode

CSS:
Define some basic styles for the accordion, using CSS.

.accordion-item {
  border: 1px solid #ccc;
  margin-bottom: .5rem;
}

.accordion-header {
  background-color: #f5f5f5;
  cursor: pointer;
  padding: .5rem;
  font-weight: 500;
}

.accordion-content {
  display: none;
  padding: .5rem;
}

.accordion-item[open] .accordion-content {
  display: block;
}
Enter fullscreen mode Exit fullscreen mode

The cursor: pointer; style makes it clear that the title is clickable.

JavaScript:
To enhance the accordion functionality and allow only one item to be open at a time, you can use JavaScript. Here's an example of how to achieve this:

document.querySelectorAll('.accordion-item').forEach((accordion) => {
  accordion.addEventListener('toggle', function() {
    if (this.open) {
      document.querySelectorAll('.accordion-item').forEach((otherAccordion) => {
        if (otherAccordion !== this) otherAccordion.removeAttribute('open');
      });
    }
  });
});
Enter fullscreen mode Exit fullscreen mode

Codepen:

Conclusion

By using the details and summary tags along with some basic CSS and JavaScript, you can create a simple and accessible accordion without relying on bulky libraries or frameworks. This method makes it easier to maintain and is more performant, leading to better user experiences. Have fun experimenting and enhancing your accordion with different styles and functionalities!

Top comments (0)