Skip to main content

HTML Summary Element

Every container in HTML that holds something important tends to have a caption that says what is inside: <figcaption> for a figure, <caption> for a table, <legend> for a fieldset, and <summary> for a <details> widget.

The summary is the part you always see, and the thing you click to open the rest. It is also the part that most often goes wrong: vague labels, hidden focus rings, headings that disappear for screen readers, and links tucked inside where they do not belong. This lesson shows how to get it right.


What You Will Learn​

  • What <summary> does and where it must go
  • Writing clear, specific summary text
  • What may and may not go inside a summary
  • How it is announced and operated (keyboard and screen readers)
  • Styling and replacing the marker
  • Why a changing "Show" and "Hide" label causes trouble
  • Accessibility, security, and global notes
  • Common mistakes

The Basics​

index.html
<details>
<summary>Opening times</summary>
<p>Saturday and Sunday, 9:00 to 18:00.</p>
</details>
style.css
summary {
cursor: pointer;
font-weight: 600;
padding-block: 0.25rem;
}

The rules are short:

RuleDetail
It belongs only inside <details>Outside a <details>, a <summary> has no special meaning
It must be the first child of the <details>The browser uses the first <summary> that is a direct child
It is always visibleWhether the widget is open or closed
It is the toggle controlClicking it, or pressing Enter or Space when it has focus, opens and closes the widget
If it is missingThe browser supplies a default label, usually "Details", which tells nobody anything

By default, a <summary> is displayed like a list item, with a marker (a small triangle) at its start. That is why you can style the marker the way you style a list bullet.

Writing Good Summary Text​

The summary is like a door sign: a visitor decides whether to open the door by reading it. It has to say what is inside.

ContentWeak summaryStrong summary
An FAQ answer"Click here""Can I bring my own apron?"
Opening hours"More""Opening times"
Technical specs"Details""Full specifications"
Terms and conditions"Read this""Booking and cancellation terms"
A hint in a puzzle"Open""Hint 2: the rule for even numbers"
A long log"Show""Build log (240 lines)"

Good habits:

  1. Name the content, not the action. The widget already tells assistive technology that it can be opened.
  2. Use a question for FAQs, using the visitor's own words.
  3. Be specific and short. A summary should be quick to scan, ideally under 10 words.
  4. Make each summary unique on the page, so a list of controls reads clearly.
  5. Use plain sentence case. Avoid ALL CAPS.
  6. Add useful hints in brackets when needed: "Download the guide (PDF, 2 MB)".

Try It: Test a Label​

Type a summary label and see how it reads and what a checker would say about it.

index.html
<!-- Weak -->
<details>
<summary>Click here for more</summary>
<p>…</p>
</details>

<!-- Strong -->
<details>
<summary>Full specifications</summary>
<p>Weight 1.2 kg. Dimensions 30 by 20 by 8 cm.</p>
</details>
script.js
const vague = ["click here", "more", "read more", "details", "info", "show", "open"];

document.querySelectorAll("details > summary").forEach((summary) => {
const text = summary.textContent.trim().toLowerCase();

if (!text) console.log("Empty summary");
else if (vague.some((word) => text === word || text.startsWith(word + " ")))
console.log("Vague summary: " + summary.textContent.trim());
});

What Can Go Inside a Summary​

The specification says a <summary> holds phrasing content (text, <strong>, <em>, <code>, <span>, <img>, and so on), optionally mixed with a heading. In practice, it is best to keep it to plain text, with light inline formatting.

Inside a summaryVerdict
Plain textBest
<strong>, <em>, <code>, <span>Fine
An <img> with alt text, or an inline icon marked aria-hidden="true"Fine, if decorative or well described
A heading (<h3>)Allowed, but see below
A link, button, or form fieldAvoid. See below
Paragraphs, lists, tables, formsNo. Put these in the hidden content, not in the summary

Headings inside a summary​

You may want the question to count as a heading, so people can navigate your FAQ by headings:

<details>
<summary><h3>Can I bring my own apron?</h3></summary>
<p>Yes.</p>
</details>

This is allowed by the specification, but support is uneven. The summary acts as a button, and a button's children are generally treated as plain text by assistive technology, so some screen readers do not announce the heading or list it in their heading navigation. A safer approach:

  • For most pages, use plain summary text. The widget list is already easy to scan.
  • If you really need real headings in the page outline, put the heading outside and keep a short, clear summary inside:
<h3 id="parking-title">Parking</h3>
<details aria-labelledby="parking-title">
<summary>Where to park</summary>
<p>Limited parking is behind the town hall.</p>
</details>

Test with the screen readers your visitors use.

Clicking a summary toggles the widget. A link or button inside it fights with that behaviour: do you open the widget, or follow the link? Different browsers and screen readers handle it differently, and it can be impossible to reach by keyboard. Keep links, buttons, and form fields in the hidden content, below the summary.

Keyboard and Screen Reader Behaviour​

With no extra code, a <summary>:

  • Is focusable (it joins the Tab order).
  • Opens and closes with Enter or Space.
  • Is announced much like a button, with its expanded or collapsed state: "Opening times, button, collapsed."
  • Shows a focus ring (unless you remove it).

You do not need role="button", tabindex="0", aria-expanded, or key handlers. Adding them is at best redundant, and at worst, it breaks things.

If you need to stop a particular summary from toggling (rare), you can prevent the default action in JavaScript, but then it is no longer a working disclosure, so consider whether you should use <details> at all:

document.querySelector("summary").addEventListener("click", (event) => {
event.preventDefault();
});

Styling the Marker​

The default marker is a small triangle. You have three options:

  1. Leave it. It is familiar, free, and works.
  2. Restyle it with summary::marker (colour, size).
  3. Replace it with your own icon, using list-style: none and a ::before pseudo-element.

Try the three styles, and see the CSS behind each:

index.html
<details>
<summary>Full specifications</summary>
<p>Weight 1.2 kg. Dimensions 30 by 20 by 8 cm. Dishwasher safe.</p>
</details>
style.css
/* Plain: restyle the built-in marker */
summary::marker {
color: #1d4ed8;
}

/* Replace the marker with a turning chevron */
summary {
list-style: none;
}

summary::-webkit-details-marker {
display: none; /* older WebKit browsers */
}

summary::before {
content: "";
display: inline-block;
width: 0.5em;
height: 0.5em;
border-right: 2px solid currentColor;
border-bottom: 2px solid currentColor;
transform: rotate(-45deg);
margin-inline-end: 0.7em;
transition: transform 0.15s;
}

details[open] > summary::before {
transform: rotate(45deg);
}

@media (prefers-reduced-motion: reduce) {
summary::before { transition: none; }
}

Things to keep in mind:

  • Always keep a visible sign of whether the item is open or closed. A summary with no marker looks like plain text, and visitors will not know it can be clicked.
  • Make the whole row clickable and large. Add padding to the summary, so the target is comfortable (at least 24 by 24 CSS pixels, ideally 44).
  • Respect reduced motion. If you animate the marker, switch it off for people who asked for less movement.
  • Do not remove the focus ring. Style it instead: summary:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 2px; }.
  • Keep the marker out of the text. Draw it with CSS, so a screen reader does not read "plus" or "greater than".

Do Not Swap "Show" and "Hide" in the Label​

A common trick uses CSS to change the label when the widget opens:

/* Not recommended */
details > summary::after { content: "Show"; }
details[open] > summary::after { content: "Hide"; }

This causes trouble:

  • Text generated by CSS is not reliably translated or read the same way by every screen reader.
  • The widget already announces "collapsed" or "expanded". A changing label adds noise, and can say the opposite of what happened ("Hide, expanded").
  • Labels that change are harder for voice control users ("click Show" stops working after it opens).

Keep the label stable, name the content, and let the state announce itself. If you want a visual cue, change the marker instead, as in the demo above.

Accessibility at a Glance​

  • Write a clear, specific, unique label that names the content.
  • Keep the summary visible, with a contrast ratio of at least 4.5 to 1.
  • Keep a visible marker that shows open and closed, and not only through colour.
  • Keep a visible focus indicator.
  • Do not put links, buttons, or form fields inside.
  • Be careful with headings inside. Test with a screen reader, or put the heading outside.
  • Do not add role, tabindex, or aria-expanded to a summary.
  • Make the target large, with padding.
  • Use icons only as decoration (aria-hidden="true"), with the meaning in the text.
  • Do not auto-open or auto-close items in ways the visitor did not ask for.

Security and Privacy Notes​

  • The summary and the content below it are both part of the page source, whether the item is open or closed. Never hide secrets, private data, or "protected" answers in a <details>.
  • Escape user-supplied text before putting it in a summary (for example a user's question in a Q&A list). Use textContent in JavaScript, not innerHTML.
  • Do not build a summary from untrusted HTML. A malicious label could add a link, a script, or a fake button.
  • Do not reveal sensitive state in the label. A summary such as "Account 4821 balance" shows that detail to anyone looking at the screen, even while the widget is closed.

Global Audience Notes​

  • Translate summaries, and keep them short, since the same idea can take much longer in another language.
  • The built-in marker flips by itself on right-to-left pages. For a custom marker, use margin-inline-end and other logical properties, so it appears on the correct side.
  • Write questions in the visitor's own words, using phrases they would really use. Machine-translated or jargon-heavy labels are hard to scan.
  • Avoid idioms and wordplay in labels, which translate badly.
  • Do not rely on the marker alone to show that an item can be opened. Some visitors will not recognise the symbol.
  • Check that all-capital labels do not hurt readability in your languages. Capitalisation rules differ, and some scripts have no capital letters at all.

Common Mistakes to Avoid​

  1. Leaving out the <summary>, so the label is a generic "Details".
  2. Putting the <summary> anywhere but first.
  3. A vague label: "Click here", "More", "Info".
  4. Changing the label between "Show" and "Hide".
  5. Putting links, buttons, or inputs inside the summary.
  6. Relying on a heading inside the summary for page navigation, without testing.
  7. Removing the marker and the focus ring with no replacement.
  8. Adding role="button", tabindex, or aria-expanded to the summary.
  9. Putting long paragraphs, lists, or forms inside the summary.
  10. Using the same label for many items.
  11. All-capital labels.
  12. Using <summary> outside <details>, expecting it to do something.

Practice Time​

Try these in your editor:

  1. Build a <details> with a clear <summary>, and remove the summary to see the default label.
  2. Rewrite five vague labels ("More", "Click here", "Info", "Open", "Details") as specific ones.
  3. Add padding and a pointer cursor to a summary, and check the click area.
  4. Restyle the marker colour with summary::marker.
  5. Replace the marker with a "+" and "βˆ’" using ::before.
  6. Replace it with a rotating chevron, and add a reduced-motion rule.
  7. Give the summary a :focus-visible style, and tab to it.
  8. Put a link inside a summary, and test how it behaves with the mouse and the keyboard. Then move the link into the content.
  9. Try a heading inside a summary, and listen with a screen reader's heading list.
  10. Bonus: turn five questions from your own site's FAQ into <details> items with good summaries.

Quick Recap​

Click a question to check your answer.

1. What is the <summary> element for?

It is the always-visible label of a <details> widget, and also the control that opens and closes it. It must be the first child of the <details>.

2. What makes a good summary label?

A short, specific, unique phrase that names the content (such as "Opening times" or a real FAQ question), not an action like "Click here" or "Show more".

3. What should you avoid putting inside a summary?

Links, buttons, and form fields, which conflict with the toggle behaviour, and long block content. Headings are allowed, but support in screen readers is uneven, so test them.

4. Do you need ARIA or tabindex on a summary?

No. It is focusable, works with Enter and Space, and is announced as a button with its expanded or collapsed state. Adding role, tabindex, or aria-expanded is redundant and can cause conflicts.

5. How can you change the triangle marker?

Restyle it with summary::marker, or hide it with list-style: none (plus summary::-webkit-details-marker { display: none } for older WebKit) and draw your own with ::before. Always keep a visible open and closed cue, and respect reduced motion.

6. Why not swap the label between "Show" and "Hide"?

The widget already announces collapsed or expanded, so a changing label adds noise and can contradict the state. CSS-generated text may not be translated or read reliably, and voice control commands based on the old label stop working.

Key Takeaways​

  • <summary> is the visible label and toggle of a <details>, and must be its first child.
  • It is operated by Enter, Space, or a click, and announced like a button with an expanded or collapsed state, with no ARIA needed.
  • Write specific, short, unique labels that name the content, and avoid "Click here" and "More".
  • Keep summaries to plain text and light inline formatting. Avoid links, buttons, and fields inside them, and test headings before relying on them.
  • You can restyle or replace the marker with CSS, but always keep a visible open and closed cue, a focus ring, and a large target.
  • Keep the label stable. Do not swap "Show" and "Hide".
  • Everything in a summary and its content is in the page source, so never hide secrets there, and escape user-supplied text.
  • Plan for translation, right-to-left layouts, and visitors who do not recognise the marker.

Next, learn how to create pop-ups that need attention, in Dialog, or return to the Semantic HTML overview.