
Zero JavaScript Accordions with HTML5 Details and Summary
Expandable FAQ sections and collapsible disclosure widgets are among the most frequently over-engineered components on the web. Developers often reach for JavaScript click handlers, manual aria-expanded toggling, and height animations when native HTML5 already provides the <details> and <summary> elements with built-in keyboard (Enter and Space) and screen-reader support.
Example
<details>
<summary>What is Clean Markup?</summary>
<p>Writing semantic, accessible, and standards-compliant HTML, CSS, and JavaScript.</p>
</details>
Input : Frequently Asked Questions list
Output : Keyboard-accessible expandable accordion using pure HTML5 and CSS.
Implementation
<section class="faq-section" aria-labelledby="faq-heading">
<h2 id="faq-heading">Frequently Asked Questions</h2>
<details class="faq-item" open>
<summary class="faq-item__summary">
Why use native <details> instead of a custom div?
</summary>
<div class="faq-item__content">
<p>
The browser automatically manages focus, keyboard activation, and
announces the expanded or collapsed state to assistive technology.
</p>
</div>
</details>
<details class="faq-item">
<summary class="faq-item__summary">
Can we style the disclosure triangle in CSS?
</summary>
<div class="faq-item__content">
<p>
Yes—you can hide the default marker using
<code>summary::-webkit-details-marker</code> and replace it with a
custom CSS indicator that rotates when <code>details[open]</code> is active.
</p>
</div>
</details>
</section>
.faq-item {
border: 1px solid #dedede;
border-radius: 6px;
margin-bottom: 12px;
background: #ffffff;
}
.faq-item__summary {
padding: 16px 20px;
font-weight: 700;
color: #082840;
cursor: pointer;
list-style: none;
display: flex;
justify-content: space-between;
align-items: center;
}
.faq-item__summary::-webkit-details-marker {
display: none;
}
.faq-item__summary::after {
content: "+";
font-size: 20px;
color: #04ae92;
transition: transform 150ms ease;
}
.faq-item[open] .faq-item__summary::after {
transform: rotate(45deg);
}
.faq-item__content {
padding: 0 20px 18px 20px;
color: #424242;
}
Main Point: Adding the open boolean attribute to <details open> renders that item expanded on initial page load while remaining interactive.
Credits
Photo by Jess Bailey