<details> and <summary> to Show/Hide Content

The <details> tag specifies additional details that the user can open and close on demand.

The <details> tag is often used to create an interactive widget that the user can open and close. By default, the widget is closed. When open, it expands, and displays the content within.

Any sort of content can be put inside the <details> tag.

Tip: The <summary> tag is used in conjunction with <details> to specify a visible heading for the details.

Example

Specify details that the user can open and close on demand:

<details>
  <summary>Epcot Center</summary>
  <p>Epcot is a theme park at Walt Disney World Resort featuring exciting attractions, international pavilions, award-winning fireworks and seasonal special events.</p>
</details>

Creating an open disclosure box

To start the <details> box in its open state, add the Boolean open attribute:

<details open>
  <summary>System Requirements</summary>
  <p>
    Requires a computer running an operating system. The computer must have some
    memory and ideally some kind of long-term storage. An input device as well
    as some form of output device is recommended.
  </p>
</details>

Multiple named disclosure boxes

We include several <details> boxes, all with the same name so only one can be open at a time:

<details name="reqs">
  <summary>Graduation Requirements</summary>
  <p>
    Requires 40 credits, including a passing grade in health, geography,
    history, economics, and wood shop.
  </p>
</details>
<details name="reqs">
  <summary>System Requirements</summary>
  <p>
    Requires a computer running an operating system. The computer must have some
    memory and ideally some kind of long-term storage. An input device as well
    as some form of output device is recommended.
  </p>
</details>
<details name="reqs">
  <summary>Job Requirements</summary>
  <p>
    Requires knowledge of HTML, CSS, JavaScript, accessibility, web performance,
    privacy, security, and internationalization, as well as a dislike of
    broccoli.
  </p>
</details>

Styling the Marker

The <summary> element is set to a display of list-item. So the default arrow (▶) that comes with it can be altered just like the default markers on HTML list items. We can change the character that's used, and independently change its color. We need to style the ::marker pseudo-element.

Changing the Marker Color and Font Size

summary::marker {
  color: #e162bf;
  font-size: 1.2em;
}

Changing the marker spacing

By default, the marker arrow is pretty close to the summary text. Its list-style-position is set to inside. If we change it to outside, we can add space between the summary text and the marker by adding some left padding. We also need to add some left margin so that the triangle doesn't hang outside the container:

summary {
  list-style-position: outside;
  margin-left: 30px;
  padding: 10px 10px 10px 20px;
  border-radius: 5px;
}

Changing the marker shape

The marker on our <summary> element doesn't have to be a triangle. We can replace it with any character we please:

summary {
  list-style-type: '⬇ ';
}

Note that we've used '⬇ ' (with a space next to the arrow), which is an alternative to the spacing we tried above.

We now have a down arrow instead of a triangle. But … that down arrow won't change when the <details> element is open. That's because the <details> element has two states — closed and open — and we've only set the marker style for the closed state. So let's also set a marker for the open state:

details[open] > summary {
  list-style-type: '⬆ ';
}

This time, we've used an up-pointing arrow.

Removing the custom marker

As with list item markers, we can remove the marker altogether:

summary  {
  list-style: none;
}

The code above doesn't work in Safari, but there's a proprietary -webkit- option in this case, and the following does work:

summary::-webkit-details-marker {
  display: none;
}

Note: another way to remove the marker from the <summary> element is to give the <summary> element a display value of something other than list-item — such as block or flex. This works in every browser except ... Safari.

Now our element has no marker!

Making the summary element look like a tab

We’ve been setting the <summary> element to full width, but it doesn’t have to be. We could make it look more like a tab, with this simple change:

summary {
  display: inline-flex;
}

Limiting the width of the details element

In all of our examples so far, the <details> element has stretched to the full width of its container, because it’s a block-level element. We can give it a different width, however, if we don’t want it so wide, such as width: 50%;. Or we could could set it to an inline display so that it’s just as wide as its content:

details {
  display: inline-block;
}

Using Background Images

Using a background image as a marker

We could place an image on the background, like so:

summary {
  list-style: none;
  padding: 10px 10px 10px 40px;
  background: url(arrow.svg) no-repeat 14px 50%;
  background-size: 18px;
  font-weight: bold;
}

The downside of using a background image directly on the <summary> element is that we can't rotate it when the <details> element is open, because animations can't be set directly on background images in CSS. (We could, of course, use a different image for the open state, but we still couldn't animate it, which is much more fun.) So if we're going to use a background image, it's better to place it on an element that can be rotated and/or animated.

Using a background image as a marker with ::after

Let’s put the background image within an ::after pseudo-element:

summary {
  display: flex;
}

summary::after {
  content: '';
  width: 18px;
  height: 10px;
  background: url('arrow.svg');
  background-size: cover;
  margin-left: .75em;
  transition: 0.2s;
}

details[open] > summary::after {
  transform: rotate(180deg);
}

We’ve used display: flex on the <summary> element to make it easy to position the arrow horizontally.

The nice thing about this setup is that we can add animation to the arrow. (The animation doesn’t seem to work in Safari.)

Other Styling

Placing the marker arrow at the far end of the summary

Let’s do something a bit different now, placing the marker arrow on the right-hand side of the <summary> element. Because we’ve been using display: flex, moving the arrow to the far right is as easy as adding justify-content: space-between to the <summary> element:

summary {
  display: flex;
  justify-content: space-between;
}

Using ::after as a marker without a background image

There are other ways we could use ::after without an actual image. Here’s an example that uses just ::after with borders:

summary::after {
  content: '';
  width: 0;
  height: 0;
  border-top: 10px solid #15171b;
  border-inline: 7px solid transparent;
  transition: 0.2s;
}

Now we have an arrow that rotates between the closed and open state. We’ve also added a nice drop shadow to the <details> element.

Another way to use ::after without an image is to place Unicode characters within the content property:

summary::after {
  content: "\25BC";
  transition: 0.2s;
}

This sets a triangle shape (▼) as our marker, as shown in this CodePen demo.

There are thousands of Unicode symbols, and they’re quite fun to explore.

Hover effect on the details element

We can set various hover effects on the <details> element. For example, we might do something like this:

details {
  transition: 0.2s background linear;
}

details:hover {
  background: #dad3b1;
}

While we’re at it, let’s also transition the <summary> text color in the open state:

details > summary {
  transition: color 1s;
}

details[open] > summary {
  color: #d9103e;
}


        


        

Changing summary content in open and closed states

In the demos above, the <summary> has always had the same text, whether the <details> element is open or closed. But we could change that. Firstly, let’s leave the current “Click me” text in place, but also add some extra text for each state using the ::after pseudo-element:

summary::after {
  content: " to show hidden content";
}

details[open] summary::after {
  content: " to hide extra content";
}

Changing the summary cursor

The default cursor (or mouse pointer) for the <details> element is kind of weird. It’s a standard arrow for the most part, and a text pointer (or I-beam) when hovering over the <summary> text.

For fun, let’s change to the hand cursor (or “pointer”):

summary {
  cursor: pointer;
}

This sets the mouse pointer to a hand when hovering anywhere over the <summary> element

Styling a heading inside the summary

Some developers, concerned about the structure of their HTML, like to place a heading element inside the <summary> element. Whether that’s useful or not is up for debate, but the default rendering is not nice, with the heading sitting on the line below the arrow. This can be fixed by setting the heading to display: inline or display: inline-block:

summary h2 {
  display: inline;