details & summary

The `<details>` and `<summary>` elements give you a native, keyboard-accessible disclosure widget with no JavaScript. The browser handles open/close toggling, focus management, and the toggle event.

HTML5 min readConcept 40 of 42

What details and summary do

The <details> element is a disclosure widget: it has two states, collapsed and expanded, and toggles between them when the user interacts with its <summary> child. In the collapsed state only the summary is visible. In the expanded state the full content appears. The open boolean attribute controls which state the element is in -- when present, it is expanded. You can set it in HTML (<details open>) to start a widget already open. JavaScript can read and set el.open as a boolean property.

The <summary> must be the first child of <details>. It is the visible label that acts as the toggle button -- the browser gives it role="button" automatically, so it receives keyboard focus, can be activated with Space or Enter, and is announced correctly by screen readers. If you omit <summary>, browsers generate a fallback label that typically reads "Details". The triangle marker before the summary is a CSS ::marker pseudo-element and can be replaced or hidden.

Why native beats a custom accordion

A hand-rolled accordion built from <div> elements requires you to manage: a button with correct aria-expanded and aria-controls, a panel with id and correct hidden state, keyboard event handlers for Space and Enter, focus trapping or not, and open/closed state in JavaScript. The <details> element handles all of this for free. The browser manages aria-expanded, the toggle event, keyboard activation, and focus order. Content inside an open <details> is automatically in the tab order; content inside a closed one is not.

The name attribute (supported in modern browsers from 2024) creates an exclusive accordion: multiple <details> elements with the same name value behave like a radio group -- opening one closes the others. This replaces an entire class of JavaScript that developers have been writing for decades.

How to use details and summary

The minimal pattern is <details><summary>Question</summary><p>Answer</p></details>. To start it open, add the open attribute: <details open>. To listen for state changes, add an event listener for the toggle event: el.addEventListener('toggle', () => { if (el.open) { ... } }). The event fires after the state has changed.

For an exclusive accordion where only one panel can be open at a time, give all <details> elements the same name attribute: <details name="faq">. The browser enforces mutual exclusion. For an animated version, listen for the toggle event and use GSAP (or a CSS max-height transition) to animate the content region.

To customise the marker, target summary::marker { content: '' } or summary { list-style: none } (for webkit compatibility) and add your own icon. You can also use summary::-webkit-details-marker { display: none } for older Safari.

Try it

Click summaries to open and close disclosure panels, and toggle exclusive mode to see the name attribute enforce a single-open accordion.

What is the difference between defer and async?▾

defer downloads in parallel and executes in order after HTML parsing. async downloads in parallel and executes immediately when done, in no guaranteed order.

When should I use <summary> vs a custom button?▾

Use <summary> inside <details> for disclosure widgets. The browser handles role=button, keyboard activation (Space/Enter), aria-expanded, and focus management automatically.

Can I animate the open/close transition?▾

Yes. Listen for the toggle event on the <details> element. When el.open is true, GSAP-animate the content from height 0 to auto. When false, animate back to 0, then remove the open attribute.

Open state

el.open = false
el.open = false
el.open = false

HTML pattern

<!-- Basic -->
<details>
  <summary>Question</summary>
  <p>Answer</p>
</details>

<!-- Exclusive accordion (name groups them) -->
<details name="faq">...</details>
<details name="faq">...</details>

<!-- Start open -->
<details open>...</details>

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1Where must the <summary> element be placed inside <details>?
  2. 2Multiple <details name='faq'> elements are on the page. What happens when you open one?
  3. 3When does the toggle event fire on a <details> element?

Remember this

  • <summary> must be the first child of <details>. Content comes after it.
  • The open attribute controls state. Add it to HTML for an initially open widget. Read/set el.open in JS.
  • name creates an exclusive accordion group: only one <details> with that name can be open at a time.
  • The toggle event fires after state changes -- use it to trigger GSAP animations.

Done with this concept?

Mark it complete to track your progress. No login needed.