On the Web, most buttons are probably plain, and sometimes you need to add a little click effect to them to emphasize the brand or fulfill a particular function. For example, anyone who has used Ant Design will have noticed that there is a subtle water wave animation when a button is clicked

This is very distinctive, seeing a button like this will naturally lead to Ant Design.

The animation process is actually not complicated, look at the official implementation, it is realized by changing the property dynamically through JS. When clicking, the property is changed to trigger the animation, and when the animation is over, the property is restored (the restoration is to ensure that there is still an animation in the next click), as follows

Looks like a little trouble? This effect is also possible with pure CSS, and many more interesting effects can be achieved

Take a look

CSS transition animation

There are usually two ways to animate CSS, transition and animation. In general, simple actions that require active triggering (:hover, :active, or dynamic switching of class names, etc.) can be implemented with Transition, and other actions can be implemented with animation.

Going back to this example, the animation is simple enough. There are only two changes that need to be triggered actively, so the preference is transition.

If you look at the whole animation, it’s actually a superposition of two effects

  1. The shadows are growing
  2. Decreasing transparency

So, the two states of this animation (transition) can be represented like this

/* Initial state */
button{
  opacity:.4;
  transition:.3s;
}
/* Diffusion state */
button{
  box-shadow: 0 0 0 6px var(--primary-color);
  opacity: 0;
}
Copy the code

Well, now that I’ve styled both states, how do I trigger a click?

Second, CSS click animation

To complete the basic style, assume the following HTML structure

<button class="button">Default</button>
Copy the code

Just to make it look good

:root{
  --primary-color: royalblue;
}
.button{
  padding: 5px 16px;
  color: # 000000d9;
  border: 1px solid #d9d9d9;
  background-color: transparent;
  border-radius: 2px;
  line-height: 1.4;
  box-shadow: 0 2px # 00000004.cursor: pointer;
  transition:.3s;
}
.button:hover{
  color: var(--primary-color);
  border-color: currentColor;
}
Copy the code

Then add a shadow spread animation, which is rendered separately with the :: After pseudo-class for easy transparency control

.button::after{
  content: ' ';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  opacity: 0.4;
  transition:.3s;
}
Copy the code

This might be done if the normal way of thinking is to trigger the transition animation with :active

.button:active::after{
  box-shadow: 0 0 0 6px var(--primary-color);
  opacity: 0;
}
Copy the code

The effect is as follows:

Well, doesn’t seem right? And then we look down

3. CSS transition reset

Why does this happen? Here’s a word :active. :active only works when the mouse is pressed down. Usually when a button is clicked, it’s gently clicked, not long pressed. If you add an animation to :active, the animation doesn’t stop when the mouse is lifted. There will also be a “fallback” transition effect.

So, is there a way to animate only when the mouse is up?

I realize is that, assuming the default is to have the shadow of transparency (0), in: quickly remove the shadow when the active (” quickly “here refers to press cancel transition animations), and then as the default is a transition, so the mouse is raised with the shadow back to have the shadow of the state, press this ensures that there is no animation, Lift triggers transition animation

The process actually goes like this:

Unanimating the transition is also very easy, just set the duration to 0, the code implementation is like this

.button::after{
  /* Other styles */
  opacity: 0;
  box-shadow: 0 0 0 6px var(--primary-color);
  transition:.3s;
}
Click the / * * /
.button:active::after{
  box-shadow: none;
  opacity: 0.4;
  transition: 0s; /* Cancel the transition */
}
Copy the code

And then, the magic comes out!

This achieves almost the same click effect as Ant Design

Other dynamic effect cases

In fact, the above provides an idea, as long as this kind of click animation, can be implemented in this way. Like a refresh button that needs to be rotated when it’s clicked

This example is a little simpler than the one above. After all, there are only rotation changes and no transparency changes. The core code is as follows

.icon{
    transform: rotate(360deg);
    transition:.5s;
}
.button:active .icon{
    transform: rotate(0);
    transition: 0s;
}
Copy the code

The full code can be accessed from Ant Design Button (codepen.io), integrated with more demos

The same principle applies to click-particle dynamics

I will not go into details here. The complete code can be accessed via button-active (codepen.io).

5. More complex animations

As mentioned earlier, simple animations can be done with transition, and more complicated ones, like the “Q flick Q flick” button

For this kind of animation, simple transition is powerless, and animation must be used to achieve it. The principle is similar

Start by defining an animation keyframe

@keyframes tada {
    from {
        transform: scale3d(1.1.1)}10%.20% {
        transform: scale3d(.9.9.9) rotate3d(0.0.1, -3deg)}30%.50%.70%.90% {
        transform: scale3d(1.1.1.1.1.1) rotate3d(0.0.1.3deg)}40%.60%.80% {
        transform: scale3d(1.1.1.1.1.1) rotate3d(0.0.1, -3deg)}to {
        transform: scale3d(1.1.1)}}Copy the code

This animation is derived from tada in Animate. CSS and can be copied directly

Then make the button move

.button{
  animation: tada 1s;
}
Copy the code

The animation might be better understood if it resets the animation when it is clicked, and resets the animation directly, so that it reruns the animation when it is lifted

.button:active{
  animation: none;
}
Copy the code

Was it surprisingly easy to achieve this?

There is a slight flaw, however, in that each time the page is refreshed, the button will actively animate (because the animation is automatic), as shown below

So, how do I avoid the animation not executing the first time I come in?

This is a trick. You can set the animation duration to 0 by default, so that it ends immediately after the first animation execution, and then restore the default animation duration when hover is used. Since the animation has ended, changing the animation duration will not trigger the animation to run again, so the implementation is

.button{
  animation: jump 0s;
}
.button:hover{
  animation-duration: 1s;
}
.button:active{
  animation: none;
}
Copy the code

This will refresh the page without animation

Next, with animate. CSS you can replace any animation, for example

The full code can be accessed from button-jump (codepen.io), integrated with more demos

Summary and explanation

The above is about the CSS click animation a few routines and some cases, in fact, is the default animation, click reset on the line. Overall, the code is very simple, but it may not be particularly smooth to understand. Here are the main implementation points:

  1. Transition for simple animations, animation for other animations
  2. Transition can be reset by setting the duration to 0
  3. The animation can be reset by setting None
  4. Reset the animation while :active. Click and the animation will run again
  5. Complex animations can take advantage of existing animation libraries, such as anmate.css
  6. Setting the animation duration to 0 prevents animation from appearing in the first rendering

Compared to JS implementations, CSS implementations have less code, faster loading, no need to wait for JS to complete loading, better experience (such as natural support for the space bar trigger), but also easier to maintain and use, directly copy a class name on the line. Finally, if you think it’s good and helpful, please like, bookmark and retweet ❤❤❤