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.