惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
V
Visual Studio Blog
F
Full Disclosure
B
Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
L
Lohrmann on Cybersecurity
月光博客
月光博客
I
Intezer
博客园 - 三生石上(FineUI控件)
Hacker News - Newest:
Hacker News - Newest: "LLM"
D
Darknet – Hacking Tools, Hacker News & Cyber Security
博客园_首页
P
Proofpoint News Feed
C
Check Point Blog
N
News | PayPal Newsroom
H
Heimdal Security Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
G
GRAHAM CLULEY
WordPress大学
WordPress大学
C
CERT Recently Published Vulnerability Notes
Y
Y Combinator Blog
Recorded Future
Recorded Future
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Tailwind CSS Blog
W
WeLiveSecurity
L
LINUX DO - 热门话题
Microsoft Azure Blog
Microsoft Azure Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Schneier on Security
Schneier on Security
爱范儿
爱范儿
Martin Fowler
Martin Fowler
U
Unit 42
T
Troy Hunt's Blog
S
Securelist
V
V2EX
V2EX - 技术
V2EX - 技术
MongoDB | Blog
MongoDB | Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
M
MIT News - Artificial intelligence
T
Tor Project blog
Cisco Talos Blog
Cisco Talos Blog
罗磊的独立博客
小众软件
小众软件
阮一峰的网络日志
阮一峰的网络日志
Vercel News
Vercel News

CSS Articles by Temani Afif

Get Ready For the Powerful CSS border-shape Property! | CSS-Tricks Let’s Play With Gap Decorations! How to Control Infinite CSS Animations (Part 2 of 2) Two Circles, One Arrow, and Anchor Positioning Making a Responsive Pyramidal Grid With Modern CSS | CSS-Tricks How to Create a CSS-only Elastic Text Effect Making Complex CSS Shapes Using shape() | CSS-Tricks Responsive Hexagon Grid Using Modern CSS | CSS-Tricks Responsive List of Avatars Using Modern CSS (Part 2) | CSS-Tricks Responsive List of Avatars Using Modern CSS (Part 1) | CSS-Tricks Perfectly Pointed Tooltips: To The Corners Perfectly Pointed Tooltips: All Four Sides Perfectly Pointed Tooltips: A Foundation Sequential linear() Animation With N Elements | CSS-Tricks Infinite Marquee Animation using Modern CSS Better CSS Shapes Using shape() — Part 4: Close and Move | CSS-Tricks Drawing CSS Shapes using corner-shape Better CSS Shapes Using shape() — Part 3: Curves | CSS-Tricks Better CSS Shapes Using shape() — Part 2: More on Arcs | CSS-Tricks Better CSS Shapes Using shape() — Part 1: Lines and Arcs | CSS-Tricks Creating Blob Shapes using clip-path: shape() Creating Flower Shapes using clip-path: shape() Custom progress element using the attr() function A CSS-Only Star Rating Component and More! (Part 2) | CSS-Tricks A CSS-Only Star Rating Component and More! (Part 1) | CSS-Tricks How to Create Wavy Boxes Using CSS Full-Bleed Layout with Modern CSS Fancy Menu Navigation Using Anchor Positioning | CSS-Tricks How to Create a Zig-Zag Box Using CSS How to Create Zig-Zag CSS Loaders Using One Element Custom Progress Element Using Anchor Positioning & Scroll-Driven Animations How to Create Filling CSS Loaders Using One Element How to Create Curved-Edge and Rounded-Edge Shapes Using CSS CSS Tricks That Use Only One Gradient | CSS-Tricks How to create Shapes with Inner Curves using CSS Mask Custom Range Slider Using Anchor Positioning & Scroll-Driven Animations How to Get the Width/Height of Any Element in Only CSS How Keyboard Navigation Works in a CSS Game How To Create Cut-Out Shapes using The clip-path property The Modern Guide For Making CSS Shapes — Smashing Magazine css-shape.com: The Ultimate Collection of CSS-only Shapes ⚡️ Sliding 3D Image Frames In CSS — Smashing Magazine CSS Tricks To Master The clip-path Property Creating Wavy Circles with Fancy Animations in CSS Modern CSS Tooltips And Speech Bubbles (Part 2) — Smashing Magazine Do you need a Tooltip or a Speech Bubble? I have created 100 using CSS 😲 Modern CSS Tooltips And Speech Bubbles (Part 1) — Smashing Magazine Creating Flower Shapes using CSS Mask & Trigonometric Functions CSS Shapes: The Triangle The Complex But Awesome CSS border-image Property — Smashing Magazine CSS Tricks to add 3D Effects to your Text CSS Responsive Multi-Line Ribbon Shapes (Part 2) — Smashing Magazine CSS Responsive Multi-Line Ribbon Shapes (Part 1) — Smashing Magazine I have made 100+ CSS-only Ribbon Shapes | The Perfect Collection 🎀 How to create a CSS-only infinite scroll animation Re-Creating The Pop-Out Hover Effect With Modern CSS (Part 2) — Smashing Magazine Re-Creating The Pop-Out Hover Effect With Modern CSS (Part 1) — Smashing Magazine How to Create CSS Ribbon Shapes with a Single Element CSS Shapes: The Ribbon Revealing Images With CSS Mask Animations — Smashing Magazine css-loaders.com: The Biggest Collection of Loading Animations (more than 500 🤯) How To Define An Array Of Colors With CSS — Smashing Magazine CSS effects on images II Shines, Perspective, And Rotations: Fancy CSS 3D Effects For Images — Smashing Magazine What's your Lucky CSS Pattern? Check It Now! How to Add a CSS Reveal Animation to Your Images Modern Layouts using CSS Grid I created 100+ unique CSS patterns | The best collection 🤩 How to Create a Custom Range Slider Using CSS CSS Shapes: The Heart CSS Shapes: Polygon & Starburst A Text Reveal Animation using CSS CSS Tip: learn CSS the easy way! How to build a CSS-only accordion How to create Breadcrumb Navigation with CSS Different Ways to Get CSS Gradient Shadows | CSS-Tricks A CSS-only responsive Stepper component A Fancy Hover Effect For Your Avatar | CSS-Tricks How to make a zoom effect using CSS Creating a Custom Cursor using CSS CSS Infinite 3D Sliders | CSS-Tricks CSS Infinite Slider Flipping Through Polaroid Images | CSS-Tricks How to create a responsive sidebar menu using CSS CSS Infinite and Circular Rotating Image Slider | CSS-Tricks Making Static Noise From a Weird CSS Gradient Bug | CSS-Tricks CSS Grid and Custom Shapes, Part 3 | CSS-Tricks Fancy Image Decorations: Outlines and Complex Animations | CSS-Tricks Fancy Image Decorations: Masks and Advanced Hover Effects | CSS-Tricks Fancy Image Decorations: Single Element Magic | CSS-Tricks How to create an infinite image slider using CSS How to Create Wavy Shapes & Patterns in CSS | CSS-Tricks How I Made a Pure CSS Puzzle Game | CSS-Tricks How to create a Tooltip/Speech Bubble using CSS CSS Grid and Custom Shapes, Part 2 | CSS-Tricks CSS Grid and Custom Shapes, Part 1 | CSS-Tricks Zooming Images in a Grid Layout | CSS-Tricks How to create a CSS-only loader with one element Exploring CSS Grid’s Implicit Grid and Auto-Placement Powers | CSS-Tricks How to create background pattern using CSS & conic-gradient Single Element Loaders: The Bars | CSS-Tricks
How to Control Infinite CSS Animations (Part 1 of 2)
Temani Afif on May 8, 2026 · 2026-05-09 · via CSS Articles by Temani Afif

Applying an infinite animation to an element is a simple task. For example, to make an element rotate indefinitely, you add the code below, and it’s done.

.box {
  animation: rotate 5s infinite linear;
}
@keyframes rotate {
  to { rotate: 1turn; }
}Code language: CSS (css)

Now, what if I ask you to interact with that rotation? Accelerate it, slow it down, stop it smoothly, etc. It would be tricky, right? The only thing we can easily do is to pause the animation using:

animation-play-state: paused;Code language: CSS (css)

In this series of articles, we will learn much more than just how to pause an infinite animation.

Article Series

Let’s jump straight into the first example.

More Speed!

Consider the following code:

.box {
  animation: 
   rotate 5s linear infinite,
   rotate 5s linear infinite paused;
  animation-composition: add;
}
.box:hover {
  animation-play-state: running;
}
@keyframes rotate {
  to { rotate: 1turn; }
}
Code language: CSS (css)

I am defining the same animation twice, with the second one paused. On hover, both are running, resulting in faster rotation!

Cool, right? This trick was made possible using animation-composition: add. A quick look at the MDN page explains everything:

The animation-composition CSS property specifies the composite operation to use when multiple animations affect the same property simultaneously.

Then

add

The effect value builds on the underlying value of the property. This operation produces an additive effect

We are applying the same animation twice, so they add up. Initially, only one rotation runs, and on hover, the second starts, making the overall rotation faster.

The result is similar to dividing the duration by 2.

animation: rotate 2.5s linear infinite;Code language: CSS (css)

Or, multiplying the rotation by 2.

@keyframes rotate {
  to { rotate: 2turn; }
}Code language: CSS (css)

In the demo below, if you hover the first box, it will have the same speed as the second box (where I am using a duration equal to 2.5s) and the third box (where I am using rotate: 2turn).

Now the question is: Why not simply adjust the duration on hover?

.box {
  animation: rotate 5s linear infinite;
}
.box:hover {
  animation-duration: 2.5s;
}
@keyframes rotate {
  to { rotate: 1turn; }
}Code language: CSS (css)

Simple, and no need to duplicate the animation or use animation-composition.

Well, it doesn’t work. The rotation is indeed faster on hover, but the element “jumps” to a random position before it accelerates. You will get a similar behavior if you keep the same duration and update the keyframes.

No need to waste time explaining why it behaves that way, but it’s by design. Keep in mind that messing with the animation values when it’s running is never a good idea. For this reason, we are here to learn a few tricks to avoid those strange behaviors.

Controlling the Speed

Now, let’s update the code and make it more flexible:

.box {
  --d: 5s; /* animation duration */
  --s: 2;  /* speed factor */
  
  --_a: rotation linear infinite;
  animation: 
    var(--_a) var(--d),
    var(--_a) calc(var(--d)/(var(--s) - 1)) paused;
  animation-composition: add;
}
.box:hover {
  animation-play-state: running;
}
@keyframes rotation {
  to {rotate: 1turn}
}Code language: CSS (css)

We make the duration and the speed factor CSS variables to easily control the animation. A speed factor of 1 means there is no acceleration (the duration of the second animation will be equal to 0). A higher value will cause acceleration; the higher the value, the faster the element will be.

The speed factor is given by the following formula. It’s a multiplier for the initial speed.

speed_on_hover = var(--s) * initial_speed

By simply changing one variable, you get a different speed on hover without touching the CSS code:

<div class="box" style="--s: 1"></div> <!-- no acceleration -->
<div class="box" style="--s: 2"></div> <!-- 2 times faster -->
<div class="box" style="--s: 8"></div> <!-- 8 times faster !! -->Code language: HTML, XML (xml)

Slow Down!

To decelerate, we use the same technique, but the second rotation needs to play in reverse. Running two rotations in the same direction will always make the overall rotation faster, but running a second rotation in the opposite direction will make it slower!

.box {
  --d: 5s; /* animation duration */
  --s: .5; /* speed factor */
  
  --_a: rotation linear infinite;
  animation: 
    var(--_a) var(--d),
    var(--_a) calc(var(--d)/(1 - var(--s))) paused reverse;
  animation-composition: add;
}
.box:hover {
  animation-play-state: running;
}
@keyframes rotation {
  to { rotate: 1turn; }
}Code language: CSS (css)

I added reverse to the second animation, and the formula is the negation of the previous one. Following the same logic, using 1 as a speed factor will do nothing, and a smaller speed factor will reduce the speed, so we are still following the same formula:

speed_on_hover = var(--s) * initial_speed

This also means we can stop the animation by setting the speed factor to 0.

<div class="box" style="--s: 1"></div> <!-- nothing will happen -->
<div class="box" style="--s: .5"></div> <!-- 2 times slower -->
<div class="box" style="--s: 0"></div> <!-- stop the animation -->Code language: HTML, XML (xml)

The first code uses a speed factor in the range [1 +infinity[ to accelerate, while the second code uses a speed factor in the range [0 1] to decelerate.

What about negative values?

When adding two rotations that move in opposite directions, the final direction will be the one of the faster rotation. If we use values in the range [0 1], the first rotation is always faster than the second, so we get a deceleration while keeping the same direction.

If we use negative values, the second rotation is faster than the first one, and the direction changes. This also explains why 0 stops the elements; both rotations will have the same duration (same speed) and will negate each other (no more movement).

<div class="box" style="--s: -.5"></div>
<div class="box" style="--s: -1"></div>
<div class="box" style="--s: -4"></div>Code language: CSS (css)

Not only are the three boxes moving in opposite directions, but they also have different speeds. The speed factor still follows the same formula.

speed_on_hover = var(--s) * initial_speed

Using -1 means the same initial speed in reverse. -4 means four times the initial speed in reverse, and so on. The absolute value controls the speed, and the sign controls the direction!

The Generic Code

Let’s sum up what we have until now. Both codes have everything in common except the duration of the second animation and the reverse keyword.

For the first code, we have the following duration:

calc(var(--d)/(var(--s) - 1))Code language: CSS (css)

Where --s is a value in the range [1 +infinity[.

And for the second code, we have

calc(var(--d)/(1 - var(--s)))Code language: CSS (css)

Where --s is a value in the range ]-infinity 1].

It would be good if we could merge the two codes into a single generic one where the --s variable can take any value.

The second duration can also be written as follows:

calc(-1*var(--d)/(var(--s) - 1))Code language: CSS (css)

That negative sign is needed because the value var(--s) - 1 is negative, and the duration needs to be a positive value. But instead of using that negative sign, we can rely on the absolute value using abs():

abs(var(--d)/(var(--s) - 1))Code language: CSS (css)

If the value of --s is bigger than one, we get a positive value and abs() will do nothing (that’s the first code), and if --s is smaller than one, we get a negative value and abs() will transform it into a positive value (that’s the second code).

We have our generic code that can handle all the values of --s (acceleration, deceleration, stop, moving in the opposite direction)

.box {
  --d: 5s; /* animation duration */
  --s: 2; /* speed factor */
  
  --_a: rotation linear infinite;
  animation: 
    var(--_a) var(--d),
    var(--_a) abs(var(--d)/(var(--s) - 1)) paused;
  animation-composition: add;
}
.box:hover {
  animation-play-state: running;
}
@keyframes rotation {
  to {rotate: 1turn}
}Code language: CSS (css)

Wait, you forgot about the reverse keywords!

I won’t rely on it! Instead of using reverse, I will “reverse” the angle of rotation inside the animation. For this, I will use the sign() function like below:

@keyframes rotation {
  to {rotate: calc(sign(var(--s) - 1)*1turn)}
}Code language: CSS (css)

When --s is bigger than 1, the sign is positive (same direction), and when --s is smaller than 1, the sign is negative (reverse direction). The only drawback is that I need to define a new animation since the initial one must remain the same.

.box {
  --d: 5s; /* animation duration */
  --s: 2;  /* speed factor */
  
  animation: 
    init    linear infinite var(--d),
    control linear infinite abs(var(--d)/(var(--s) - 1)) paused;
  animation-composition: add;
}
.box:hover {
  animation-play-state: running;
}
@keyframes init {
  to {rotate: 1turn}
}
@keyframes control {
  to {rotate: calc(sign(var(--s) - 1)*1turn)}
}Code language: CSS (css)

We are done! A few lines of code and we can easily control the speed and direction of an infinite rotation using one variable.

But you told us not to mess with the animation when it’s running. Why are you updating the keyframes?

I am not “updating” the keyframes. I am “setting” them. The --s variable is fixed per element, so all the animation values are fixed and only the state changes on hover. We get a different animation for each element (based on the value of --s), but it’s not changing for the concerned element.

Here is the final code with different elements having different speed factors:

In the near future, we can keep working with one animation and reintroduce the reverse keyword using an if() condition.

.box {
  --d: 5s; /* animation duration */
  --s: 2; /* speed factor */
  
  --_a: rotation linear infinite;
  animation: 
    var(--_a) var(--d),
    var(--_a) abs(var(--d)/(var(--s) - 1)) paused
    if(style(--s < 1):reverse;else: ;);
  animation-composition: add;
}
.box:hover {
  animation-play-state: running;
}
@keyframes rotation {
  to { rotate: 1turn; }
}
Code language: CSS (css)

You can test it using the latest version of Chrome:

If you are new to if(), check this small article to understand how to correctly use it: “The Hidden Trick of Style Queries and if()

More Examples

We studied the entire logic with rotation in mind, but the trick works with any kind of infinite animation!

Here is an example from a previous article: “Infinite Marquee Animation using Modern CSS” where I am animating offset-distance. Hover to adjust the speed/direction of the animation:

Another example with a glowing border animation. For this one, I am animating a CSS variable, which is interesting because variables can be used almost everywhere, which means you can apply this technique to any CSS value.

We can even consider two interactions like the animated gallery below. A faster animation if you click the right arrow and a faster animation with a direction change if you click the left arrow.

This time, I am considering three animations. Initially, only one is running, and each button click will run a different animation.

.container:has(+ button:active) img {
  animation-play-state: running, paused, running; /* 1st and 3rd */
}
.container:has(+ * + button:active) img {
  animation-play-state: running, running, paused; /* 1st and 2nd */
}Code language: CSS (css)

The Math Behind The Formula

Now that we have our working code, let’s dissect the logic behind the formula I used to define the duration. I should have started with this, but I decided it wasn’t useful for understanding the overall idea, so I made this section last. Feel free to skip it if you are not interested in the math.

I wanted to have a speed factor that allows me to have the following relation between the initial speed and the speed on hover:

speed_on_hover = var(--s) * initial_speed

This makes the control intuitive as the number makes sense from a user perspective.

The initial_speed is the speed of the first animation (since the second one is paused), and the speed_on_hover is the sum of the speed of both animations (since we have an add composition). It means we have the following formula as well:

speed_on_hover = initial_speed + speed_of_second_animation

Merging both formulas, we get the following:

var(--s) * initial_speed = initial_speed + speed_of_second_animation
initial_speed * (var(--s) - 1) = speed_of_second_animation
speed_of_first_animation * (var(--s) - 1) = speed_of_second_animation

A speed can be expressed as a distance/duration, and in our case, we have two animations that animate the same way but with different durations, which leads us to:

(var(--s) - 1)/duration_of_first_animation = 1/duration_of_second_animation
duration_of_second_animation = duration_of_first_animation/(var(--s) - 1)

That translates to the CSS we used:

.box {
  --d: 5s; /* animation duration */
  --s: 2; /* speed factor */
  
  --_a: rotation linear infinite;
  animation: 
    var(--_a)      var(--d),
    var(--_a) calc(var(--d)/(var(--s) - 1)) paused
  animation-composition: add;
}Code language: CSS (css)

And when using the reverse keyword, the second animation will run in the opposite direction, so we consider the same math with a -1 in the formula.

.box {
  --d: 5s; /* animation duration */
  --s: 2; /* speed factor */
  
  --_a: rotation linear infinite;
  animation: 
    var(--_a)      var(--d),
    var(--_a) calc(var(--d)/(1 - var(--s))) reverse paused
  animation-composition: add;
}Code language: CSS (css)

Conclusion

That’s all for this first part. Thanks to the mechanism behind animation-composition, we were able to create a code that lets us easily control the speed and direction of any infinite animation. Can you think about a good use case for this technique? If so, share your demo in the comments section.

Article Series