CSS exclusive accordion

Example

Group title

Heading one

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eligendi eum eaque veniam corporis sequi consequuntur repudiandae quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum, commodi tempore temporibus tempora!

Heading two

Find-me. Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eligendi eum eaque veniam corporis sequi consequuntur repudiandae quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum, commodi tempore temporibus tempora!

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eligendi eum eaque veniam corporis sequi consequuntur repudiandae quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum, commodi tempore temporibus tempora!

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eligendi eum eaque veniam corporis sequi consequuntur repudiandae quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum, commodi tempore temporibus tempora!

Heading three

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eligendi eum eaque veniam corporis sequi consequuntur repudiandae quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum, commodi tempore temporibus tempora! find-me.

Code

HTML

Option 1. This uses group role so is not included in a page summary or table of contents by assistive technologies.

Copy 👋<div role="group" aria-labelledby="group-name">
<span id="group-name" hidden >
about group for screen readers. </span>

<details name="anyname" open>
<summary>Heading one</summary>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
  Eligendi eum eaque veniam corporis sequi consequuntur repudiandae 
  quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum,
  commodi tempore temporibus tempora!
</p>
</details>

<details class="details-scroll" name="anyname">
 <summary>Heading two</summary>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
  Eligendi eum eaque veniam corporis sequi consequuntur repudiandae 
  quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum,
  commodi tempore temporibus tempora!
</p>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
  Eligendi eum eaque veniam corporis sequi consequuntur repudiandae 
  quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum,
  commodi tempore temporibus tempora!
</p>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
  Eligendi eum eaque veniam corporis sequi consequuntur repudiandae 
  quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum,
  commodi tempore temporibus tempora!
</p>
</details>

<details name="anyname">
<summary>Heading three</summary>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
  Eligendi eum eaque veniam corporis sequi consequuntur repudiandae 
  quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum,
  commodi tempore temporibus tempora!
</p>
</details>
</div>

Option 2. Section with aria-labelledby. This is used above and is included in the page summary or table of contents by assistive technologies.

Copy 👋<section aria-labelledby="group-label">
<!-- The visually-hidden to be used if not for sighted users -->
<h2 id="group-label" class="visually-hidden">Group title</h2>

<details name="anyname" open>
<summary>Heading one</summary>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
  Eligendi eum eaque veniam corporis sequi consequuntur repudiandae 
  quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum,
  commodi tempore temporibus tempora!
</p>
</details>

<details class="details-scroll" name="anyname">
 <summary>Heading two</summary>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
  Eligendi eum eaque veniam corporis sequi consequuntur repudiandae 
  quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum,
  commodi tempore temporibus tempora!
</p>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
  Eligendi eum eaque veniam corporis sequi consequuntur repudiandae 
  quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum,
  commodi tempore temporibus tempora!
</p>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
  Eligendi eum eaque veniam corporis sequi consequuntur repudiandae 
  quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum,
  commodi tempore temporibus tempora!
</p>
</details>

<details name="anyname">
<summary>Heading three</summary>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
  Eligendi eum eaque veniam corporis sequi consequuntur repudiandae 
  quibusdam porro nemo aut facilis maxime laboriosam eveniet eos cum,
  commodi tempore temporibus tempora!
</p>
</details>
</section>

Notes:

  • These are grouped via the shared name attribute of "anyname".
  • With this attribute as one is opened another closes.
  • The first <details> is set to "open". This can be added to any.
  • We can add a heading within a summary, but it loses its meaning.
  • In page search work in details*
*This should be true for all browsers by 2026. Chromium support already there.

CSS

Copy 👋details* {
 margin: 0;
 }

 details > * {
 padding-inline: var(--space-m); 
 font-size: var(--step-0);     
 }

 details {
 background-color: var(--shade);
 overflow: hidden; 
 }

 /* Height animation*/
   
 @media (prefers-reduced-motion: no-preference) {
 details::details-content{
 transition: block-size .5s,
 content-visibility .5s;
 transition-behavior: allow-discrete; 
 }
 }

 details::details-content {
 block-size: 0;
 }

 details[open]::details-content { 
 block-size: auto; 
 }

 /* Fixed height with overflow. 
 Odd results with nth-child so a class was used.
 */

 details[open].details-scroll::details-content { 
 block-size: 12rem; 
 overflow-x: auto;
 }

 summary {
 font-size:var(--step-1); 
 font-weight:700;   
 padding-block: var(--space-s); 
 cursor: pointer;
 position: relative;
  }
  
 summary::before,
 summary::after {
 transition: .2s;
 }

 summary::before,
 summary::after {
 content: '';
 }

 summary::before, summary::after { 
  inline-size: .75em; 
  block-size: 0; 
  border-block-end: 2px solid; 
  position: absolute; 
  inset-block-start: calc(50% - 1px); 
  inset-inline-end: 2rem; 
  transform: translateY(-50%); 
}

 summary::after {
 transform: rotate(90deg);
 transform-origin: 50% 50%;

 }
 [open] summary::after {
 transform: rotate(0deg);
 }

 details p {
 padding-block-end: var(--space-s);
 }

 summary::marker {
 content: none; 
 }

/* Hides the marker on Safari. 
 Thanks to daveden.co.uk */
 summary::-webkit-details-marker {
    display: none;
 }


/* Relative color to darken the hover*/
 summary:hover{
 background-color: hsl(from var(--shade) h s calc(l + -2));
 transition: .2s ease-in;  
 }

Addtional CSS

Copy 👋/* This is in my CSS reset.
It is needed to animate the opening of <details> */

html {
  interpolate-size: allow-keywords;
}

/* This is in my utility CSS file.
Needed if hiding the <h2> shown in HTML option 2 (above) */

.visually-hidden {
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	block-size: 1px;
	overflow: hidden;
	position: absolute;
	white-space: nowrap;
	inline-size: 1px;
}

/* This adds an outline for those using high contrast themes */
details {
outline: 0.4rem solid transparent;
 }
Also see our discussion on accordions.