Is it possible to animate the transition between the open/close state of the <details>
element with just CSS?

- 30,306
- 7
- 46
- 75
-
you can try animating the height of it – Huangism Jun 25 '13 at 15:41
-
Relevant suggestion here also https://stackoverflow.com/questions/38213329/how-to-add-css3-transition-with-html5-details-summary-tag-reveal – joelostblom Jan 09 '19 at 19:42
4 Answers
No, not currently. Yes, but only if you know the height
or can animate the font-size
.
Originally, this wasn't the case. From http://html5doctor.com/the-details-and-summary-elements/, "...if you could use CSS transitions to animate the opening and closing, but we can’t just yet." (There is a comment at HTML5 doctor near the end, but it appears to require JS to force the CSS animation.)
It was possible to use different styles based on whether it's opened or closed, but transitions didn't "take" normally. Today, however, the transitions do work if you know the height
or can animate the font-size
. See http://codepen.io/morewry/pen/gbJvy for examples and more details.
This was the 2013 solution that kind of fakes it:
CSS (May need to add prefixes)
/* http://daneden.me/animate/ */
@keyframes fadeInDown {
0% {
opacity: 0;
transform: translateY(-1.25em);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
.details-animated[open] {
animation-name: fadeInDown;
animation-duration: 0.5s;
}
HTML
<details class="details-animated">
<summary>CSS Animation - Summary</summary>
Try using [Dan Eden's fadeInDown][1] to maybe fake it a little. Yay, some animation.
</details>
This works today:
CSS (May need to add prefixes)
.details-animated {
transition: height 1s ease;
}
.details-animated:not([open]) { height: 1.25em; }
.details-animated[open] { height: 3.75em; }
PS: Only tested in Chrome. Hear FF still doesn't support IE and Edge prior to version 79 still don't support details
in general.details
.
(You can use keyframe animations or transitions to do all sorts of other animations for open. I've chosen fadeInDown
for illustration purposes only. It is a reasonable choice which will give a similar feel if you are unable to add extra markup or will not know the height of the contents. Your options are, however, not limited to this: see the comments on this answer that include two alternatives, including the font-size
approach.)
-
It's a shame it doesn't work. BTW I copied your example in a fiddle and it didn't work, I don't see any change. – olanod Jun 25 '13 at 16:30
-
It works for me, but it will only work with `-webkit`, `-moz`, and `-o` (this is a reduced-code example). I was also editing that up until just now. Codepen.io has a "prefix free" option for CSS--I don't recall if JSFiddle does? Verify latest code and might want to try adding the prefixes. – morewry Jun 25 '13 at 16:36
-
-
Optionally, animate `font-size` like http://stackoverflow.com/a/30531678/923745 for visual expansion. – Steven Vachon Feb 14 '17 at 18:03
-
That's a good technique to know, but it has issues in this case. First, CSS transitions as used in example don't work, not only because of the `height` issue. Using `opacity: 0` on `details` will hide `summary` and `font-size: 0` will be inherited by `summary`. This makes `summary` invisible when `:not([open])` so it can't be opened (or it jarringly disappears after click). These issues must be worked around with keyframe animations, additional wrapping elements, and additional styles. In cases where that's possible, it does help with height; so thanks! I added it to the pen. – morewry Feb 15 '17 at 03:24
-
It works if you apply the animation to `details[open] > summary ~ *`, but requires a container around the collapsible content. – Steven Vachon Feb 15 '17 at 20:31
-
As I said, "additional wrapping elements"; as that can be a constraint. – morewry Feb 17 '17 at 08:34
My short answer is : you can not transition between summary and the rest of the details content.
BUT!
You can do some nice transition inside the summary between the selector details and details[open]
details{
position: relative;
width: 100px;height: 100px;
perspective: 1000px;
}
div{
position: absolute;
top: 20px;
width: 100px;height: 100px;
background: black;
}
details .transition{
transition: 1s linear;
transform-origin: right top;
;
}
details[open] .transition{
transform: rotateY(180deg);
background: orangered;
}
<details>
<summary>
<div></div>
<div class="transition"></div>
</summary>
</details>
NB : I answer this because it was the first result from googling on this!

- 156
- 1
- 4
Given the height has to snap at some point I prefer to start to animate the height and then snap. If your lucky enough to have all the elements a similar height this solution can be quite effective. (you do need a div inside your details elements though)
@keyframes slideDown {
0% {
opacity: 0;
height: 0;
}
100% {
opacity: 1;
height: 20px; /* height of your smallest content, e.g. one line */
}
}
details {
max-width:400px;
}
details[open]>div {
animation-name: slideDown;
animation-duration: 200ms;
animation-timing-function:ease-in;
overflow:hidden;
}
see http://dabblet.com/gist/5866920 for example

- 1,330
- 1
- 14
- 22
Of course it's possible:
DETAILS[open] SUMMARY ~ * {
animation: sweep 3s ease-in-out;
}
@keyframes sweep {
0% {
opacity: 0;
margin-left: -10px
}
100% {
opacity: 1;
margin-left: 0px
}
}
<details>
<summary>Summary content</summary>
Test test test test.
</details>

- 2,973
- 27
- 38

- 30
- 3
-
4While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. Please read this [how-to-answer](http://stackoverflow.com/help/how-to-answer) for providing quality answer. – thewaywewere Jun 10 '17 at 12:16