Can I replace the expand icon (▶) of the <details> element?

I use the <details> element in my website and I want to change the design of the expand/collapse arrows. Is it possible to set a picture instead of the existing characters?

Also, is it possible to change the position of the arrows? I want it to be on the right side and not next to the summary text.


Since <summary> has display: list-style, customising the disclosure marker can be done by setting the list-style-type property:

details > summary {
    list-style-type: '▶️';
}

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

details {
    border: 1px solid gray;
    border-radius: 0.2rem;
    padding: 0.5rem;
}

details[open] > summary {
    margin-bottom: 0.5rem;
}
<details>
<summary>An example</summary>

With some example text shown when expanded.
</details>

Unfortunately some current-generation browsers (ahem, Safari …) still don’t support this. One workaround is to set list-style: none, and then provide a custom content via the ::marker pseudo-element. This can still be used to provide further customisations. Except … well, Safari also doesn’t support ::marker, it only supports the non-standard ::-webkit-details-marker. And it doesn’t support setting custom contents within it. So instead we need to hide the element and set the actual icon via ::before:

details > summary {
    list-style-type: none;
}

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

details > summary::before {
    content: '▶️';
}

details[open] > summary::before {
    content: '🔽';
}

details {
    border: 1px solid gray;
    border-radius: 0.2rem;
    padding: 0.5rem;
}

details[open] > summary {
    margin-bottom: 0.5rem;
}
<details>
<summary>An example</summary>

With some example text shown when expanded.
</details>

Is it possible to set a picture instead of the existing characters?

This is certainly possible ─ setting the baskground image to your icon and setting the original marker's colour to transparent will produce this effect.

Example:

details summary::-webkit-details-marker {
    background: url(/images/toggle-expand.png) center no-repeat;
    color: transparent;
}
details[open] summary::-webkit-details-marker {
    background: url(/images/toggle-collapse.png) center no-repeat;
    color: transparent;
}

This only works in Webkit browsers and Chrome. You might want to consider rotating the icon instead of replacing it with a different one, in which case you can use the following:

summary::--webkit-details-marker {
    transform: rotate(-90deg);
}

details[open] summary::--webkit-details-marker {
    transform: rotate(0deg);
}

[dir="rtl"] summary::--webkit-details-marker {
    transform: rotate(90deg);
}

[dir="rtl"] details[open] summary::--webkit-details-marker {
    transform: rotate(0deg);
}

This solution rotates the icon if it is originally pointing downwards. It also factors in details elements that are within RTL parents; though be careful with this approach if mutliple text directions are used throughout the document.