The <details> element creates a native disclosure widget. Its <summary> is the control; everything else inside <details> is the content it reveals.
Out of the box
No JavaScript required.
No ARIA required.
No classes required.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Details and summary</title>
</head>
<body>
<h1>Frequently asked questions</h1>
<details>
<summary>Do I need JavaScript?</summary>
<p>No. The browser manages the disclosure state and keyboard interaction.</p>
</details>
</body>
</html>Click the summary or focus it and press Enter or Space. The browser toggles the boolean open attribute on <details>.
Open by default
Add open when the content should begin expanded.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Open details</title>
</head>
<body>
<details open>
<summary>Shipping estimate</summary>
<p>Most orders arrive in 3–5 business days.</p>
</details>
</body>
</html>open is a boolean attribute. Its presence means open, so open="false" is still open. Remove the attribute to close the disclosure.
A group of disclosures
Multiple <details> elements are independent by default. This is often better than an accordion because people can compare answers without repeatedly reopening them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Disclosure group</title>
</head>
<body>
<h1>Account help</h1>
<details>
<summary>Change my email address</summary>
<p>Open Profile, choose Contact information, and enter your new address.</p>
</details>
<details>
<summary>Reset my password</summary>
<p>Use the “Forgot password?” link on the sign-in screen.</p>
</details>
<details>
<summary>Delete my account</summary>
<p>Contact support. We will confirm the request before removing data.</p>
</details>
</body>
</html>A native exclusive accordion
Give related <details> elements the same name and the browser will keep only one open at a time.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Native accordion</title>
</head>
<body>
<h1>Course outline</h1>
<details name="course" open>
<summary>Chapter 1: HTML</summary>
<p>Structure, semantics, forms, and native interaction.</p>
</details>
<details name="course">
<summary>Chapter 2: CSS</summary>
<p>Layout, responsive design, states, and animation.</p>
</details>
<details name="course">
<summary>Chapter 3: JavaScript</summary>
<p>Application behavior, data, and progressive enhancement.</p>
</details>
</body>
</html>Older browsers that do not understand name still get functional disclosures; they simply allow more than one to remain open.
Use an accordion on purpose
Hiding content adds interaction cost. Keep important, short content visible. Use an exclusive accordion only when opening one section at a time genuinely helps—not merely to make a page look shorter.
The toggle event
JavaScript is optional, but <details> exposes a toggle event when application logic needs to react to its state.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Details toggle event</title>
<script src="/script.js" defer></script>
</head>
<body>
<details id="delivery">
<summary>Delivery details</summary>
<p>Your package will require a signature.</p>
</details>
<p id="status" aria-live="polite">Delivery details are closed.</p>
</body>
</html>const details = document.querySelector('#delivery');
const status = document.querySelector('#status');
details.addEventListener('toggle', () => {
status.textContent = `Delivery details are ${details.open ? 'open' : 'closed'}.`;
});The .open property reflects the open attribute and can also be changed directly:
const details = document.querySelector('details');
details.open = true;
details.open = false;
Styling the disclosure
Now that the native behavior is established, we can change its appearance. Keep the summary’s focus state and open/closed state obvious.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/styles.css" />
<title>Styled details</title>
</head>
<body>
<main>
<h1>Field guide</h1>
<details open>
<summary>Eastern bluebird</summary>
<div class="details__content">
<p>Look for a bright blue back, rusty chest, and low, wavering flight.</p>
</div>
</details>
<details>
<summary>American goldfinch</summary>
<div class="details__content">
<p>Listen for a series of musical twitters during its bouncing flight.</p>
</div>
</details>
</main>
</body>
</html>* { box-sizing: border-box; }
body {
background: hsl(227 30% 17%);
color: hsl(0 0% 96%);
font: 1.125rem/1.6 system-ui, sans-serif;
margin: 0;
min-block-size: 100dvh;
padding: 2rem;
}
main {
inline-size: min(100%, 42rem);
margin-inline: auto;
}
details {
border-block-end: 1px solid hsl(227 15% 40%);
}
summary {
cursor: pointer;
font-size: 1.25rem;
font-weight: 700;
padding-block: 1rem;
}
summary::marker {
color: hsl(47 100% 60%);
}
summary:hover {
color: hsl(47 100% 70%);
}
summary:focus-visible {
outline: 3px solid hsl(190 90% 55%);
outline-offset: 4px;
}
.details__content {
padding: 0 1.5rem 1rem;
}
.details__content > :last-child {
margin-block-end: 0;
}[ A11y Checklist ]
- Put a
<summary>first inside every<details>. - Write a summary that describes the hidden content; avoid vague labels such as “More.”
- Do not add
role="button",tabindex, or keyboard handlers. The browser already supplies the interaction. - Avoid links, buttons, or other interactive controls inside
<summary>; competing actions make the control confusing. - Preserve a strong
:focus-visiblestyle if you replace browser styling. - Do not hide critical instructions, errors, or information a user must discover immediately.
- Test zoom and long content: opening a disclosure should not make the next action difficult to find.