Have 30-200 Employees? Make $50k-$500k selling your data for AI Training.

Learn More

20 Simple Ways to Style the HTML details Element

Ralph Mason
Ralph Mason
Published in
·Updated:

The AI briefing for Developers

Stay up to date with AI tools, model releases, and developer workflows that matter.

Weekly. Free. One click to leave.

Share this article

20 Simple Ways to Style the HTML details Element
SitePoint Premium
Stay Relevant and Grow Your Career in Tech
  • Premium Results
  • Publish articles on SitePoint
  • Daily curated jobs
  • Learning Paths
  • Discounts to dev tools
Start Free Trial

7 Day Free Trial. Cancel Anytime.

Key Takeaways

  • Enhance the visual appeal of the `
    ` element by adding borders, padding, and background colors to distinguish it from other content.
  • Customize the default marker of the `` element using CSS properties for color, spacing, and shape, or replace it with custom characters or images.
  • Utilize CSS pseudo-elements like `::after` to create dynamic, custom markers that can be animated or styled independently from the `` text.
  • Experiment with hover effects, animations, and content transitions within the `
    ` element to enrich user interaction and visual engagement.
  • Address accessibility and usability by modifying focus styles and cursor types, ensuring that the element is user-friendly across different browsing methods.

In this article, we’ll look at some simple ways to style the HTML

element, which is a very useful element for revealing and hiding bits of content on a web page.

It’s handy to have a simple disclosure element in HTML that doesn’t require JavaScript, but the default styling of the

element might be a turn-off for some. Fortunately, it’s quite easy to change the styling of this element.

The table of contents below is an example of the

element in use. We’ve added a simple border to it, along with some padding.

Table of Contents

Introducing the details Element

Here’s the basic code for the

element:

Click me!

Peekaboo! Here's some hidden content!

Basically any HTML content can be placed inside the

element. The element provides the prompt for the user to click on the element to reveal more content, and it must be the first child of the
element.

Here’s a live example of this code:

Click me!

Peekaboo! Here’s some hidden content!

Let’s look at all the ways we can use CSS to enhance the appearance of our

element.

Background Colors, Borders and Padding

A really simple way to enhance the look of the

element is to add some padding along with a border or some background colors.

Adding a border

As shown in the table of contents above, a simple border can do a lot to enhance and define the

element, along with some padding and a slight border radius:

details {
  padding: 10px; 
  border: 5px solid #f7f7f7;
  border-radius: 3px;
}

That’s the simple code we’ve used above to style our ToC.

Adding some background color

Let’s add a background color to our

element instead of a border:

details {
  padding: 10px;
  background-color: #e4eaef;
  border-radius: 5px;
}

The result is shown in the Pen below.

The background color gives the element better definition, and the padding helps to create some space inside it.

We can also give a different background color to the

element to distinguish it from the rest of the content, and change its text color:

summary {
  background-color: #2196F3;
  color: white;
  padding: 10px;
}

Note that changing the text color of the

element also changes the color of the marker arrow. That’s because the marker is actually attached to the element just as markers (such as bullets) are attached to list items. We’ll see below how to style them separately.

Styling the Marker

The

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.

Changing the marker color

Let’s set the default marker to a different color. Just for fun, let’s also bump up the font size of the marker. We can do this with the ::marker pseudo-element:

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

The result is shown below.

It’s a nice, simple solution, although ::marker unfortunately isn’t supported in Safari, so see other options below if that’s a dealbreaker.

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;
}

The result is shown below.

I’ve exaggerated the spacing between the arrow marker and the summary text just to make it obvious. Unfortunately, using list-style-position: outside; with the

element doesn’t work in Safari. Fortunately, there are other options, as we’ll see below.

Changing the marker shape

The marker on our

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

element is open. That’s because the
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. This gives us the result shown below.

Damn! Once again, Safari lets us down, as it doesn’t support list-style-type on the

element either. Don’t despair, though, as we’ll look at fancier solutions below.

We can try all sorts of other characters, such as + and –, ✓ and Χ or ✗, ⋁ and ⋀ , and even have fun with other characters like ★ or colorful fruits like 🍏 🍌 🍓 🍋 and 🍐, but remember that these characters may not work on all systems, so be a little careful, and once again, list-style-type certainly won’t work in Safari.

Creating a Custom Marker for the summary Element

As we saw above, even though we can set a different character for the default marker, and give it styles such as color and font size, there can be issues with doing so. A better option might be to remove the marker altogether and create a completely custom alternative.

Removing the custom marker

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

summary  {
  list-style: none;
}

/* sigh, Safari again */

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

The standard list-style: none works on all browsers except … (can you guess?) … Safari. At least there’s a proprietary -webkit- option in this case.

Note: another way to remove the marker from the

element is to give the element a display value of something other than list-item — such as block or flex. This works in every browser except … (do I even need to say it?) … Safari.

Now our element has no marker.

Having no marker gives no visual prompt at all that this element is clickable, so it’s not a great idea to leave it at that.

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 result is shown below.

The downside of using a background image directly on the

element is that we can’t rotate it when the
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);
}

Here’s a live demo of this code.

We’ve used display: flex on the

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, but the behavior is good enough, and I’m getting a bit fed up with this browser!)

Making the summary element look like a tab

We’ve been setting the

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;
}

An example is shown below.

Limiting the width of the details element

In all of our examples so far, the

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;
}

Click on the tab below to reveal the narrower width of the

element.

Try changing display: inline-block to width: 50% in the Pen above.

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

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 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;
}

Here’s a live demo.

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

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. Each comes with a code like U + 25BC or U + 025BC. To use that code inside the content property, take the characters after the + and place them inside the content quotes, with a \ at the front: content: "\25BC". If there’s one or more zeros at the start, you can leave them out. (For example, U + 02248 can become "\02248" or "\2248".)

Miscellaneous Extras

So far, the things we’ve done above are more than enough, but there are other things we can have fun with, so let’s just play with a few of them here.

Hover effect on the details element

We can set various hover effects on the

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

text color in the open state:

details > summary {
  transition: color 1s;
}

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

The result is shown below.

We could also just set a background change on the

element instead.

Animating the opening and closing of the details element

Haha, fooled ya! It appears it’s not possible to animate the opening and closing of the

element. According to MDN:

Unfortunately, at this time, there’s no built-in way to animate the transition between open and closed.

However, this ability is coming soon (as of late 2024) via calc-size(auto). (Here’s an example of how it might work.)

In the meantime, we can have a bit of fun by animating the contents of the

element. For example, we could set the contents to fade in once revealed:

details article {
  opacity: 0;
}

details[open] article {
  animation: fadeIn .75s linear forwards;
}

@keyframes fadeIn {
 0% {
   opacity: 0;
 }
 100% {
   opacity: 1;
 }
} 

The result is shown below.

Another trick might be to slide in the content, like so:

details {
  overflow: hidden;
}

details[open] article {
  animation: animateUp .5s linear forwards;
}

@keyframes animateUp {
  0% {
    opacity: 0;
    transform: translatey(100%);
  }
  100% {
    opacity: 1;
    transform: translatey(0);
  }
}

The result is shown below.

It’s a bit cheesy, and perhaps overkill, but worth trying anyway. Unfortunately, these animations only work the first time the element is clicked (unless the browser devtools are open, for some weird reason!). You basically need the intervention of JavaScript to make the effect work repeatedly.

Changing summary content in open and closed states

In the demos above, the

© 2000 – 2026 SitePoint Pty. Ltd.
Back to top
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
Privacy PolicyTerms of Service