Are you still throttling with JS? CSS can also prevent repeated button clicks

Directory

1. Analysis of CSS Implementation Ideas

2. Precise control of CSS animation

3. Other ideas for CSS implementation

Fourth, summarize


As we all know, function throttle is a very common optimization method in JS, which can effectively avoid the execution of functions too frequently.

For example: a save button, in order to avoid repeated submissions or server considerations, often requires certain restrictions on click behavior, such as only allowing one submission every 300ms, at this time I think most students will Directly copy a throttle function online, or directly quote the lodash tool library

btn.addEventListener('click', _.throttle(save, 300))

In fact, in addition to the JS method, CSS can also implement such a function very easily without any framework library. Let’s take a look together.

1. Analysis of CSS Implementation Ideas

CSS implementation is different from JS thinking, so we need to look at this issue from another angle.

For example, it is necessary to restrict the click event here, that is, to disable the click event. Think about how to disable the event. Yes, it is pointer-events;

Then there is a time limit. After each click, it needs to be automatically disabled for 300ms, and it will be restored after the time has passed. So, what features are related to time and state restoration? That’s right, it’s animation;

In addition, there needs to be a trigger time, here is the click behavior, so it must be related to the pseudo-class :active .

Therefore, comprehensive analysis shows that pointer-events, animation and :active are needed to realize such a function, so how to connect these ideas in series? ?

Think for 3 seconds…

Have you thought about it?

In fact, this kind of scene can be understood as control over CSS animation, for example, there is an animation control button that changes from disabled->clickable, Let this animation re-execute every time it is clicked. During the execution process, it is always in the disabled state. Does it achieve the effect of “throttling”?

Next, let’s look at the specific implementation

2. Precise control of CSS animation

Suppose there is a button, bound to a click event

<button onclick="console.log('Save')">Save</button>

At this time, the continuous click of the button will trigger continuously, the effect is as follows

Let’s define an animation about pointer-events, called throttle

@keyframes throttle {
  from {
    pointer-events: none;
  }
  to {
    pointer-events: all;
  }
}

Very simple, it is the change from disabled to clickable.

Next, bind this animation to the button. Here, for the convenience of testing, the animation is set to 2s

button{
  animation: throttle 2s step-end forwards;
}

Note that the easing function of the animation here is set to a step curve, step-end, which can easily control the change time point of pointer-events.

Those who are interested can refer to this article: An in-depth introduction to the steps function symbol in CSS3 animation attributes? Zhang Xinxu-Xin Space-Xin Life (zhangxinxu.com)[1]

As shown below, the value of pointer-events within 0~2 seconds is none, once it reaches 2 seconds, it immediately becomes all , because it is forwards, it will always maintain the state of all

Finally, re-execute the animation when clicked, just set the animation to none when pressed

This technique has been introduced in more detail in this article before: CSS implements button click animation routines

The implementation is as follows

button:active{
  animation: none;
}

For the convenience of demonstration, we temporarily add the color change to the animation

@keyframes throttle {
  from {
    color: red;
    pointer-events: none;
  }
  to {
    color: green;
    pointer-events: all;
  }
}

Now if the text is red, it means that it is disabled, only if it is green, it means that it can be clicked, it is very clear, as follows

The following is the final click comparison effect, which limits the frequency of clicks very well

The complete code is as follows, just a few lines, If you need to change the limit time, just change the animation time directly

button{
  animation: throttle 2s step-end forwards;
}
button:active{
  animation: none;
}
@keyframes throttle {
  from {
    pointer-events: none;
  }
  to {
    pointer-events: all;
  }
}

You can also check out any of the following links:

  • CSS throttle (codepen.io)[2]

  • CSS throttle – Code Nuggets (juejin.cn)[3]

  • CSS throttle (runjs.work)[4]

3. Other ideas for CSS implementation

Remember the previous article?

Are you still using the timer? Listening to events with CSS

Borrowing this idea can also easily achieve the effect of throttling. And for a better experience, you can use the real button to disable

btn.disabled = true

The specific idea is this. Use :active to trigger the transition change, and then dynamically set the disabled state of the button by listening to the transition callback. The implementation is as follows

Define an insignificant transition property, such as opacity

button{
  opacity: .99;
  transition: opacity 2s;
}
button:not(:disabled):active{
  opacity: 1;
  transition: 0s;
}

Then listen to the initial callback of transition

// transition start
document.addEventListener('transitionstart', function(ev){
  ev.target.disabled = true
})
// end of transition
document.addEventListener('transitionend', function(ev){
  ev.target.disabled = false
})

The biggest advantage of this is that this part of the disabled logic is completely decoupled from the business logic, and can be seamlessly accessed at any time and on any occasion, and is not affected by the framework and environment. The effect is as follows

The complete code can also be viewed at any of the following links:

  • CSS throttle disabled (codepen.io)[5]

  • CSS throttle disabled – Juejin Nuggets (juejin.cn)[6]

  • CSS throttle disabled (runjs.work)[7]

Four, summarize

The above implements a function similar to “throttling” through the idea of CSS. Compared with JS implementation, the implementation is more streamlined, easier to use, and has no framework restrictions. Let’s summarize the main points of implementation together:

  1. Function throttling is a very common optimization method, which can effectively avoid the execution of functions too frequently

  2. The implementation idea of CSS is different from that of JS, the focus is on finding the attributes associated with the scene

  3. ·Css to achieve “throttling” is actually to control the precise control of an animation. Suppose there is an animation control button that changes from disabled->clickable. This animation is re-executed. During the execution process, it has been in the disabled state, thus achieving the effect of “throttling”.

  4. You can also dynamically set the disabled state of the button through the callback function of the transition

  5. The advantage of this implementation is that the disabled logic and business logic are completely decoupled

However, this implementation method is still relatively limited, limited to click behaviors. In many cases, throttling may be used for scrolling events or keyboard events. Such scenarios can be implemented in traditional ways.