HTML <details> and <summary> Explained
One of the easiest ways to remove unnecessary JavaScript from a website is to use HTML features that already provide the behaviour you need.
<details> and <summary> are a perfect example.
Together, they create a section that can be opened and closed by the user. This makes them useful for FAQs, extra information, technical details, and other content that does not always need to be visible.
The basic example
<details>
<summary>What is shutter count?</summary>
<p>
Shutter count is the number of mechanical
shutter activations recorded by a camera.
</p>
</details>
That is a working disclosure section.
The user can click the summary to open it. Clicking again closes it.
No JavaScript is needed.
The <details> element has wide browser support and has been available across major browsers for years.
What <summary> does
The <summary> is the visible label for the section.
<summary>What is shutter count?</summary>
It should normally be the first child inside <details>.
The rest of the content is hidden until the section is opened.
<details>
<summary>More information</summary>
<p>Hidden until opened.</p>
<p>You can put normal HTML here.</p>
</details>
The HTML <summary> element is interactive by default, so users can also operate it with a keyboard.
Open by default
Add the open attribute:
<details open>
<summary>System requirements</summary>
<p>
This section starts open.
</p>
</details>
You can also add or remove that attribute from JavaScript if needed.
Styling the open state
When a details element is open, the open attribute is present in the HTML.
That makes it easy to style:
details {
border-bottom: 1px solid #ddd;
padding: 1rem 0;
}
summary {
cursor: pointer;
font-weight: 600;
}
details[open] summary {
margin-bottom: 0.75rem;
}
You can also change other parts:
details[open] {
background: #f7f7f7;
}
A simple FAQ
<section class="faq">
<h2>Frequently asked questions</h2>
<details>
<summary>Do I need JavaScript?</summary>
<p>No. This FAQ works with HTML alone.</p>
</details>
<details>
<summary>Can I style it?</summary>
<p>Yes. Normal CSS works.</p>
</details>
<details>
<summary>Does it work with a keyboard?</summary>
<p>Yes. The browser provides the interaction.</p>
</details>
</section>
.faq details {
border-bottom: 1px solid #ddd;
padding-block: 1rem;
}
.faq summary {
cursor: pointer;
font-size: 1.1rem;
font-weight: 600;
}
.faq details[open] summary {
margin-bottom: 0.75rem;
}
For many FAQ pages, this is all you need.
Changing the marker
Browsers normally show a small triangle next to <summary>.
You can style it with ::marker:
summary::marker {
color: #777;
}
You can also remove it:
summary {
list-style: none;
}
If you remove the native marker, make sure it is still clear that the row can be opened.
For example:
summary {
list-style: none;
display: flex;
justify-content: space-between;
gap: 1rem;
}
summary::after {
content: "+";
}
details[open] summary::after {
content: "−";
}
Now the plus changes to a minus when the section is open.
Do not use a button inside <summary>
The summary itself is already the control.
Avoid doing this:
<summary>
<button>Open</button>
</summary>
It creates nested interactive controls and can make the behaviour confusing.
Keep the summary simple:
<summary>Open details</summary>
Grouping details like an accordion
Modern HTML also supports a name attribute for grouping details elements in browsers that implement it.
<details name="faq">
<summary>Question one</summary>
<p>Answer one.</p>
</details>
<details name="faq">
<summary>Question two</summary>
<p>Answer two.</p>
</details>
When supported, opening one item in the same named group can close the other.
If this exact behaviour is important for your site, check browser support first. A normal list of independent <details> elements remains the safest simple option.
Listening for changes
You do not need JavaScript to make details work, but you can listen for the toggle event if another part of the page needs to know when it changes.
const details = document.querySelector("details");
details.addEventListener("toggle", () => {
console.log(details.open);
});
The open property is true or false.
Opening it with JavaScript
details.open = true;
Closing:
details.open = false;
Again, the useful part is that you are controlling a native HTML component rather than building the whole component yourself.
When <details> is a good fit
I like it for:
- FAQs;
- technical notes;
- optional settings;
- extra product information;
- code explanations;
- spoiler sections;
- long lists where not everything needs to be shown.
It is especially useful when the content is useful but not needed by everyone.
When it is not a good fit
Do not hide important information just to make a page look cleaner.
If every visitor needs to read something, show it normally.
For example, this would be a poor use:
<details>
<summary>Important safety information</summary>
...
</details>
if the user really needs that information before continuing.
The element is best for optional content.
SEO and hidden content
The content inside <details> is still part of the HTML.
<details>
<summary>Camera compatibility</summary>
<p>
Sony, Nikon, Canon, and other camera models...
</p>
</details>
It is not loaded later with JavaScript. It is already in the document.
That makes <details> a much simpler choice than loading FAQ answers only after a click.
Accessibility
Native HTML is usually a better starting point than rebuilding the same control from generic <div> elements.
A browser understands that <summary> is the control for <details>. Keyboard behaviour is built in, and assistive technology has useful information about the state.
That does not mean you can ignore clear text and good structure. A summary such as:
<summary>More</summary>
may not tell the user much.
Prefer something clear:
<summary>Which camera models are supported?</summary>
A complete styled example
<div class="faq">
<details>
<summary>
Does this work without JavaScript?
</summary>
<p>
Yes. Opening and closing is handled by the browser.
</p>
</details>
<details>
<summary>
Can I open one by default?
</summary>
<p>
Yes. Add the open attribute.
</p>
</details>
</div>
.faq details {
border-bottom: 1px solid #ddd;
padding: 1rem 0;
}
.faq summary {
list-style: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between;
font-weight: 600;
}
.faq summary::after {
content: "+";
font-size: 1.25rem;
}
.faq details[open] summary::after {
content: "−";
}
.faq details[open] summary {
margin-bottom: 0.75rem;
}
That is a useful FAQ component with no script at all.
Use the element that already exists
I like <details> and <summary> because they are a good example of simple web development.
You can build the same thing with JavaScript, classes, event listeners, and ARIA attributes.
Or you can use the HTML element that was made for it.
For a basic disclosure section, I will take the native version almost every time.