Here’s a nice simple demo from Moritz Gießmann on animating the triangle of a <details>
element, which is the affordance that tells people this thing can be opened. Animating it, then is another kind of affordance that tells people this thing is opening now.
The tricks?
- Turn off the default triangle:
details summary::-webkit-details-marker { display:none; }
. You can’t animate that one. - Make a replacement triangle with the CSS border trick and a pseudo element.
- Animate the new triangle when the state is open:
details[open] > summary::before { transform: rotate(90deg); }
.
This only animates the triangle. The content inside still “snaps” open. Wanna smooth things out? Louis Hoebregts’ “How to Animate the Details Element Using WAAPI” covers that.
Here’s a fork where I’ll combine them just because:
I see Moritz put the cursor: pointer;
on the summary
as well like Greg Gibson suggests.
You can also animate the details element with just css.
Less smooth than the JS solution.
But also a nice solution via css only.
The cool thing about the internet is you share something amazing and people will share something amazing back. ❤
Here is the pure css version that works like your final version that uses both css and js.
That’s cool. I didn’t know it yet. Thanks for the work from you and Moritz. stay creative!
Is there a way to animate closing with just CSS?
Yes, with a trick similar to that using a checkbox.
Move the content after the element and use your preferred way of hiding with the sibling selector
details:not([open]) + .content
.Reason:
The element hides its content programmatically. CSS can’t delay that, thus the closing animation happens after the content is hidden.
Further barrier:
Animating
height
requires a pre-calculated value,auto
won’t be animated. If the content’s height is not fixed then JS is required to measure the content and store the height in a CSS variable.A CSS-only solution is still possible by animating other properties.
If the content is absolute positioned then animating
opacity
is a good way to show/hide.If the content is within the document flow then some other trick is necessary. Animating
margin-top
of the content’s children to a big enough negative value can be a solution, albeit inefficient and hacky. But it works. Good for a no-JS fallback and if JS is enabled, it can do properheigth
animation. That however adds more maintenance and testing time.Example:
codepen[yLMmmVb][350]
I also tried to create a CSS-only solution. The closing is not smooth, but it opens somewhat gracefully: https://codepen.io/dada1smo/pen/LYydWBg