How to use Throttle with Css instead of Javascript

waterfish
3 min readNov 25, 2022

--

As we all know, function throttle is a very common optimization method in JS, which can effectively avoid the execution of functions too frequently.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.

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 on the Internet. Or directly reference the lodash tool library

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

Now we use CSS to implement thought analysis:

Here, you need to restrict the click event, that is, disable the click event. Think about how to disable the event. Yes, it is pointer-events;
Then there is the 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?

Have you thought about it?

In fact, this kind of scene can be understood as the control of CSS animation. For example, there is an animation control button that changes from disabled -> clickable, and the animation is re-executed every time it is clicked. During the execution process, it is always disabled. Did it achieve the effect of “throttling”?

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 continuously trigger the console.log, Let’s define an animation about pointer-events, called throttle

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

It’s the change from disabled to clickable.

Next, bind this animation to the button

button{
animation: throttle 0.3s 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.

As shown below, the value of pointer-events is none within 0~0.3 seconds. Once it reaches 0.3 seconds, it immediately becomes all. Since it is forwards, it will always maintain the state of all.

Finally, re-execute the animation when clicking, just set the animation to none when pressing.

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

Through the above ideas, we can also use css to disable buttons.

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

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

Then listen to the start callback of the transition

// start
document.addEventListener('transitionstart', function(ev){
ev.target.disabled = true
})
// end
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.

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.

--

--