LEARNING OBJECTIVES โต
- Understand the role of
<summary>as the interactive label for<details>. - Explore default browser fallback mechanics when
<summary>is omitted. - Master modern CSS styling for the disclosure indicator using
::marker,list-style: none, and custom SVGs. - Avoid accessibility anti-patterns such as nesting interactive controls inside
<summary>.
๐ The Mental Model & Story (Intuitive Foundation)
Imagine a physical metal filing cabinet drawer. The entire drawer represents <details>. The shiny brass handle on the front of that drawer represents <summary>.
Without that handle, you have no clear point of contact to pull the drawer open. If you walk past the filing cabinet, you don't inspect all the folders packed inside; you read the label engraved directly on the brass handle. When you press or pull on that handle, the drawer glides open to reveal the contents.
In HTML, the <summary> element serves as that exact physical handle. It is the only part of the <details> widget that remains continuously visible, whether the widget is collapsed or expanded. It intercepts keyboard and pointer interactions, acts as the focusable anchor in the accessibility tree, and visually indicates whether the drawer is open or closed via its disclosure marker.
+-------------------------------------------------------------+
| <details> |
| +-------------------------------------------------------+ |
| | <summary> [โถ] What is your refund policy? | | <-- The "Handle"
| +-------------------------------------------------------+ |
| | (Hidden until user clicks or activates the summary) | |
| +-------------------------------------------------------+ |
+-------------------------------------------------------------+
Technical Deep Dive & Specifications
The First-Child Requirement & Default Fallback
According to the WHATWG HTML Specification, if a <summary> element is present, it must be the very first element child of its parent <details> element.
<!-- Valid: <summary> is the first child -->
<details>
<summary>System Specifications</summary>
<p>Memory: 64GB DDR5</p>
</details>
<!-- Invalid Markup: Non-summary content appears before <summary> -->
<details>
<p>Preamble text here...</p> <!-- Parser issue: Browser relocates or treats as content -->
<summary>System Specifications</summary>
<p>Memory: 64GB DDR5</p>
</details>
What Happens When <summary> is Omitted?
If a developer creates a <details> element without a <summary> child, the HTML specification mandates that the user agent must provide a default synthetic summary. In English-locale browsers, this synthetic summary displays the localized text "Details" alongside a default disclosure marker.
<!-- HTML authored without <summary> -->
<details>
<p>This paragraph is hidden by default.</p>
</details>
<!-- User Agent renders a synthetic summary labeled "Details" -->
Keyboard Navigation & Accessibility Semantics
The <summary> element is natively interactive. It is mapped to the browser's Accessibility Tree with an implicit role="button" and an automatic aria-expanded state.
| Interaction / Semantic Property | Specification Behavior |
|---|---|
Tab Order (tabindex) |
Naturally included in the sequential tab navigation order (tabindex="0" equivalent). |
| Keyboard Activation | Pressing either Enter or Space toggles the parent <details> widget. |
| Accessibility Role | Maps to a button that controls disclosure (role="button" / disclosure trigger). |
| Screen Reader Announcement | Announces label text, role, and current state ("System Specifications, button, collapsed" or "expanded"). |
Customizing and Replacing the ::marker Indicator
By default, browsers render a disclosure triangle using the CSS list-style mechanism. The triangle is part of the ::marker pseudo-element.
+-----------------------------------+
| summary { display: list-item; } |
+-----------------------------------+
|
+---------------+---------------+
| |
Standard Modern CSS Legacy WebKit Engine
summary::marker { color: red; } summary::-webkit-details-marker { display: none; }
Technique 1: Styling the Native Marker
summary::marker {
color: #2563eb;
font-size: 1.1em;
}
Technique 2: Removing the Marker Completely to Use Custom SVG Icons
To build custom accordion headers, developers remove the default marker across all browser engines using standard and legacy reset rules:
/* Remove default disclosure triangle across modern browsers and legacy Safari */
summary {
list-style: none; /* Modern standard */
display: flex;
align-items: center;
justify-content: space-between;
}
/* WebKit-specific legacy reset */
summary::-webkit-details-marker {
display: none;
}
Semantic Headings Inside <summary>
When structuring FAQs, documentation manuals, or legal terms, each section title needs to appear in the document outline. Is it valid to put an <h3> inside a <summary>?
Yes. The WHATWG specification allows phrasing and heading content inside <summary>.
<!-- Correct Semantic Heading Integration -->
<details>
<summary>
<h3>Frequently Asked Questions: Billing & Invoicing</h3>
</summary>
<p>Invoices are generated on the 1st of every calendar month...</p>
</details>
[!IMPORTANT] Do NOT wrap
<details>or<summary>inside a heading tag (e.g.,<h3><summary>...</summary></h3>is invalid HTML). The heading tag must be placed inside the<summary>element.
The Nested Interactive Elements Anti-Pattern
According to HTML and ARIA specifications, interactive elements (such as <a>, <button>, <input>, or <select>) must never be nested inside <summary>.
<!-- โ CRITICAL ACCESSIBILITY ANTI-PATTERN -->
<summary>
Terms of Service
<a href="/legal.pdf" target="_blank">Download PDF</a> <!-- FORBIDDEN -->
<button type="button">Print</button> <!-- FORBIDDEN -->
</summary>
Why this breaks:
- Event Collision: Clicking the download link or button triggers both the link's action and the parent summary's toggle action.
- Accessibility Failure: Assistive technologies (screen readers) announce the summary as a button. When a button contains an internal link or button, screen readers cannot properly convey the control hierarchy to blind users.
๐ป Interactive Code Playground
Starter Code
Line-by-Line Code Breakdown
- Lines 24โ36: Sets
list-style: noneon<summary>anddisplay: noneonsummary::-webkit-details-markerto reliably strip the default browser disclosure marker across Chrome, Firefox, and Safari. - Lines 26โ28: Applies
display: flexandjustify-content: space-betweento spread the text label and the custom SVG chevron to opposite edges of the container. - Lines 37โ40: Uses the
:focus-visiblepseudo-class to ensure keyboard users navigating with Tab receive an accessible focus ring without causing unsightly outlines on mouse clicks. - Lines 50โ54: Defines the CSS selector
details[open] summary .chevron-iconto rotate the SVG icon 180 degrees smoothly when the parent details widget opens. - Lines 65โ72: Houses both the question text and the vector SVG inside the
<summary>handle without introducing any illegal nested interactive elements.
Expected Browser Render Output
- Initial State: A card displaying "What payment methods do you accept?" on the left, with a subtle gray downward chevron
โตon the far right. No default browser triangle is visible. - Keyboard Focus: Pressing Tab draws a crisp 2px blue focus outline around the summary row.
- Activation: Pressing Space or clicking rotates the chevron smoothly upside-down
โ, turns it blue, and displays the explanatory payment method paragraph below.
๐๏ธ Hands-On Exercise
๐ฏ The Challenge: Design a Branded FAQ Component with Heading Hierarchy
Build an accessible FAQ section for a cloud hosting provider adhering to the following strict specifications:
- Create two `