---
title: "::details-content: Style Expandable Content, No Wrappers"
description: "The ::details-content pseudo-element lets you style the expandable content of details elements separately from the summary, no divs needed."
canonical: "https://www.trevorlasn.com/blog/details-content-pseudo-element"
author: "Trevor I. Lasn"
published: "2025-11-11"
last-updated: "2026-11-08"
topics: ["CSS", "HTML"]
---

# ::details-content: Style Expandable Content, No Wrappers

The ::details-content pseudo-element lets you style the expandable content of details elements separately from the summary, no divs needed.

By Trevor I. Lasn · Published 2025-11-11 · Updated 2026-11-08 · https://www.trevorlasn.com/blog/details-content-pseudo-element

The `::details-content` pseudo-element solves a problem that existed since [`<details>`](https://www.trevorlasn.com/blog/html-details-element) was introduced: you couldn't style the content area without wrapping it in a div.

## Update: Fixed the summary selector and the demo

The CSS examples and the demo below first used `details::summary`, which isn't a real pseudo-element, so browsers dropped those rules. They now use `details > summary`, which targets the `<summary>` element itself.

The demo also styled its text with `::details-content p`, which browsers drop too, because a pseudo-element can't take a descendant selector. Now its summaries, arrows and answer text get the styles they were meant to have.

The padding and top border also moved from `::details-content` to the `<p>` inside it. A closed `::details-content` still paints its padding and border, which left an empty band under every closed item.

[Browser support for `details-content` on webstatus.dev](https://webstatus.dev/features/details-content)

The problem: you want the summary and content to look different, so you'd need to add a wrapper div just for styling:

```html
<!-- The old way: wrapper required for styling -->
<details>
  <summary>How do I return an order?</summary>
  <div class="content-wrapper">
    <p>
      Visit your order page and click "Return Item". You'll receive a prepaid
      shipping label via email within 24 hours.
    </p>
  </div>
</details>
```

```css
details > summary {
  padding: 1rem;
  background: white;
}

.content-wrapper {
  padding: 1rem;
  background: #f9fafb;
  border-top: 1px solid #e5e7eb;
}
```

Now with `::details-content`, forget the wrapper:

```html
<!-- Clean HTML, no wrapper needed -->
<details>
  <summary>How do I return an order?</summary>
  <p>
    Visit your order page and click "Return Item". You'll receive a prepaid
    shipping label via email within 24 hours.
  </p>
</details>
```

```css
details > summary {
  padding: 1rem;
  background: white;
}

details::details-content {
  background: #f9fafb;
}

details > p {
  margin: 0;
  padding: 1rem;
  border-top: 1px solid #e5e7eb;
}
```

Here's what that looks like in action:

You can also animate it:

```css
details::details-content {
  opacity: 0;
  transition:
    opacity 300ms,
    content-visibility 300ms allow-discrete;
}

details[open]::details-content {
  opacity: 1;
}
```

This fades the content in/out smoothly when opening and closing. The `allow-discrete` keyword lets `content-visibility` participate in the transition—important for performance when you have lots of content inside.

`::details-content` hit Baseline status in September 2025, so it works everywhere: Chrome 131+, Firefox 143+, Safari 18.4+, and Edge 131+. For older browsers, fall back to wrapper divs.

Use it for FAQs, documentation sidebars, expandable menus, pricing tiers, anything where the content needs to look different from the trigger. You get cleaner HTML, less CSS, full control over the content area, and no semantic compromises.
