We are interested to emulate the after-click animation effect from Ant Design’s Button page. We can see that whenever we click on the button, there is a subtle radiate effect. In this post we will see how we can achieve it using just CSS and then TailwindCSS.
Background
I believed it is not as well-known to create an after-click animation using just pure CSS. CSS does provides the :hover
and :active
selectors for developers to style when we mouse hover and mouse press on the button, and it is not obvious how we can provide an animation after a click event. At least for me, I didn’t know how to do it. A quick google search led me to this demo from w3schools which gave me a huge help on how to achieve it.
CSS only implementation
Here is the code with CSS.
.app-btn {
position: relative;
border-radius: 9999px;
border: 1px solid #60a5fa;
background: white;
padding: 0.5rem 1rem;
font-weight: 500;
color: #60a5fa;
transition:
color 300ms ease-out,
border-color 300ms ease-out,
background-color 300ms ease-out;
transform-style: preserve-3d;
}
.app-btn:hover {
border-color: #93c5fd;
background-color: #eff6ff;
color: #93c5fd;
}
.app-btn:active {
border-color: #2563eb;
background-color: #d2e3fc;
color: #2563eb;
}
.app-btn:before {
content: "";
border-radius: 9999px;
background-color: #60a5fa;
position: absolute;
opacity: 0;
z-index: -10;
inset: -8px;
transition: all 300ms ease-out;
transform: translateZ(-1px);
}
.app-btn:active:before {
inset: 0;
opacity: 1;
transition: none;
}
Explanation of the CSS code
The general idea is to use the pseudo element (:before
or :after
) as an extra layer below (using a negative z-index
) the button layer, then animate the CSS inset
property to negative to have the pseudo element scale up and at the same time animate the opacity to achieve the radiate effect. The question is how do we trigger “after-click” here? The trick is in the :active:before
selector, where we set the start of the animation and also more importantly, setting the transition
to none
so as not to trigger any animation going from “non-active” to “active”. And once the user released the mouse on the button, we go from “active” to “non-active” and this is where we want the animation to start.
There is also an unusual use of transform-style: preserve-3d
and transform: translateZ(-1px)
in the CSS code above. This is to fix an issue of z-index
-ed pseudo element not showing up. There is a stackoverflow issue about this.
TailwindCSS implementation
Here is the code using TailwindCSS classes for those interested.
.app-btn {
@apply before:absolute
before:inset-[-8px]
before:-z-10
before:rounded-full
before:bg-blue-300
before:opacity-0
before:transition-all
before:duration-300
before:ease-out
before:content-['']
active:before:inset-0
active:before:opacity-100
active:before:transition-none
relative
rounded-full
border
border-blue-500
bg-white
px-4 py-2
font-medium
text-blue-500
transition-colors duration-300
hover:border-blue-400
hover:bg-blue-50
hover:text-blue-400
active:border-blue-600
active:bg-blue-100
active:text-blue-600;
transform-style: preserve-3d;
}
.app-btn:before {
transform: translateZ(-1px);
}
Note that
transform-style: preserve-3d
andtransform: translateZ(-1px)
is not provided by TailwindCSS, so we might want to add it into the our own custom utility layer.
Button in action
Notice the subtle radiate effect after clicking on the button.
Conclusion
Doing after-click animation in CSS is not as obvious and intuitive as it seems. However understanding that we can control between the event lifecycle from “non-active” to “active” and “active” to “non-active” separately is essential to create the behavior that we want in this use-case.