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

推荐订阅源

Google DeepMind News
Google DeepMind News
C
CERT Recently Published Vulnerability Notes
C
Cisco Blogs
Cloudbric
Cloudbric
The Last Watchdog
The Last Watchdog
L
LINUX DO - 热门话题
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Security Archives - TechRepublic
Security Archives - TechRepublic
TaoSecurity Blog
TaoSecurity Blog
V2EX - 技术
V2EX - 技术
H
Heimdal Security Blog
S
Security Affairs
L
Lohrmann on Cybersecurity
Hacker News - Newest:
Hacker News - Newest: "LLM"
Simon Willison's Weblog
Simon Willison's Weblog
WordPress大学
WordPress大学
小众软件
小众软件
Security Latest
Security Latest
AWS News Blog
AWS News Blog
Apple Machine Learning Research
Apple Machine Learning Research
GbyAI
GbyAI
Engineering at Meta
Engineering at Meta
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
F
Full Disclosure
S
Schneier on Security
L
LangChain Blog
MyScale Blog
MyScale Blog
Know Your Adversary
Know Your Adversary
P
Privacy International News Feed
Google Online Security Blog
Google Online Security Blog
Scott Helme
Scott Helme
Stack Overflow Blog
Stack Overflow Blog
爱范儿
爱范儿
A
Arctic Wolf
Martin Fowler
Martin Fowler
B
Blog RSS Feed
大猫的无限游戏
大猫的无限游戏
博客园 - 三生石上(FineUI控件)
The Register - Security
The Register - Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园_首页
Latest news
Latest news
F
Fortinet All Blogs
G
GRAHAM CLULEY
T
The Exploit Database - CXSecurity.com
Hacker News: Ask HN
Hacker News: Ask HN

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 1 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 2 of 2)
Temani Afif on May 15, 2026 · 2026-05-16 · via CSS Articles by Temani Afif

Time for part 2! This time, we will see how to start/stop infinite animations smoothly. The goal is to make the effect look natural and realistic. As in the previous article, we will study the effects using rotation and then explore additional examples.

Article Series

Smooth Starts

Hover the element in the demo below:

The element starts rotating slowly, then reaches a constant speed. And when you unhover, it will slowly stop as well. Cool, right? It’s even more satisfying if you keep hovering/un-hovering.

That effect is made possible like this:

.box {
  animation: rotate 2s linear infinite paused;
  transition: transform 1s ease-out;
}
.box:hover {
  animation-play-state: running;
  transform: rotate(-.2turn);
}
@keyframes rotate {
  to { rotate: 1turn; }
}Code language: CSS (css)

I am still using the same technique I used in the first article, where I consider two rotations with an additive effect, but this time, we don’t have two animations. We have an animation and a transition.

On hover, two things happen at the same time:

  1. The infinite linear animation starts to play (it’s paused initially): The element rotates from 0turn to 1turn with a duration of 2s
  2. A transition is triggered: The element rotates from 0turn to -.2turn with a duration of 1s.

During the first second, the transition will rotate the element in the opposite direction, creating a “brake” effect on the first animation. After that, the linear behavior of the first animation takes the lead, and we get a rotation at constant speed.

When you unhover, the animation pauses and the transition is triggered in the opposite direction, rotating the element from -.2turn to 0turn. This gives us a smooth stop.

Choosing the right values is very important for the illusion to work. If the transition is too fast or too slow compared to the animation, the effect will be bad. Even the easing is crucial to have a realistic effect.

Here are a few bad examples:

I don’t have a formula to share for this effect because I simply did some trial & error. It was quite easy to find values that performed well.

The same code can be adjusted slightly to have the animation running initially and smoothly stop it on hover:

.box {
  animation: rotate 2s linear infinite paused;
  transition: transform 1s ease-out;
}
.box:not(:hover) {
  animation-play-state: running;
  transform: rotate(-.2turn);
}
@keyframes rotate {
  to { rotate: 1turn; }
}Code language: CSS (css)

I simply changed :hover with :not(:hover)!

You can also write it this way:

.box {
  animation: rotate 2s linear infinite;
  transition: transform 1s ease-out;
}
.box:hover {
  animation-play-state: paused;
  transform: rotate(.2turn);
}
@keyframes rotate {
  to { rotate: 1turn; }
}Code language: CSS (css)

We start with the animation running, then pause it on hover. We also remove the negative sign from the rotation used with the transition.

More Examples

The main trick relies on the fact that we can express rotation using two different properties (transform and rotate), but this won’t be possible for other properties because, as far as I know, only rotate and translate can be defined using two different properties.

That said, we can still find other alternatives to achieve the same effect. Here is an example using the infinite marquee animation. Hover to start the animation

The main animation uses offset-distance to move the elements from left to right, and to have the opposite movement, I used a negative translate.

img {
  animation: 
    x linear infinite var(--d) 
    calc(-1*sibling-index()*var(--d)/sibling-count()) paused;
  transition: translate .8s ease-out;
}
.container:hover img {
  animation-play-state: running;
  translate: -50px;
}
@keyframes x { 
  to { offset-distance: 100%; }
}Code language: CSS (css)

Let’s take the example of the glowing border:

For this one, I am using CSS variables:

img {
  mask: 
    conic-gradient(#000 0 0) content-box,
    linear-gradient(calc(45deg + var(--a) + var(--b)), 
      #0000 30%,#000 40% 60%,#0000 70%) subtract,
    conic-gradient(#000 0 0) padding-box;
  
  animation: rotation 2s linear infinite paused;
  transition: --b .8s ease-out;
}
img:hover {
  animation-play-state: running;
  --b: -.2turn;
}
@keyframes rotation {
  to {--a: 1turn}
}Code language: CSS (css)

The angle of the gradient is defined as the sum of two variables --a and --b. The first variable will have the linear infinite animation, and the second variable will have the transition effect. Since I am adding them, I get the “additive effect”!

This code can be considered generic because any value can be expressed as a sum of two variables, and as long as you register both variables using @property, you can animate them.

Here is the initial code written using variables:

.box {
  rotate: calc(var(--a) + var(--b));
  animation: rotate 2s linear infinite paused;
  transition: --b 1s ease-out;
}
.box:hover {
  animation-play-state: running;
  --b: -.2turn;
}
@keyframes rotate {
  to { --a: 1turn; }
}Code language: CSS (css)

And it works the same way:

In this case, I would use the first version as it is less verbose, but if you are unable to express a movement and its opposite using properties, you can rely on CSS variables, which work in all cases.

Stop There!

We can control the speed of infinite animations and smooth out their stopping and starting, but what about controlling the stop position? It would be interesting to hover an infinite animation and smoothly stop it at the same position.

A demo worth a thousand words:

On hover, the element will always return to the same position. And when you unhover, the animation runs again.

For this effect, I am going to ditch animations and keyframes and rely on something else. I will define an infinite animation using @starting-style.

@property --a {
  syntax: "<angle>";
  inherits: false;
  initial-value: -100turn; 
}
.box {
  rotate: var(--a);
  transition: --a 200s linear;
  @starting-style {
    --a: 0turn;
  }
}Code language: CSS (css)

The code looks strange, but the logic is pretty simple. I am registering the variable --a with an initial value equal to -100turn. The @starting-style block will define a “starting” value equal to 0turn. This means that on page load, the element will “start” with a value equal to 0turn that updates to the value -100turn and since we are applying a transition, we get a smooth change.

The use of large values creates the illusion of an infinite animation. The value will animate from 0turn to -100turn in 200s which is equivalent to 1 turn every 2 seconds for more than 3 minutes. You can go even bigger if 3 minutes aren’t enough.

Now, we introduce a new variable and update the code as follows:

@property --a {
  syntax: "<angle>";
  inherits: false;
  initial-value: -100turn; 
}
@property --i {
  syntax: "<number>";
  inherits: false;
  initial-value: 1; 
}
.box {
  rotate: calc(mod(var(--a),1turn)*var(--i));
  transition: --i 0s,--a 200s linear;
  @starting-style {
    --a: 0turn;
  }
}
.box:hover {
  --i: 0;
  --a: 0turn;
  transition: --i .8s ease-out,--a 0s .8s;
}Code language: CSS (css)

The rotation formula is very important. I am using mod()to make sure the value gets clamped to the range [0 1turn] then I multiply that value by the variable --i which is set to 1 initially.

Until now, we still have our infinite rotation. The only change is the rotate value, but it won’t affect the visual result. Instead of going from 0turn to -100turn, we will go from 0turn to 1turn 100 times.

Now let’s see what happens on hover. Let’s suppose our element is at .3turn when we hover it. The transition on hover will update the value of --i with a duration equal to .8s and the value of --a instantly after a delay equal to .8s. In other words, we first update the value of --i to make it equal to 0 then we update the value of --a to make it 0 as well.

The first update of --i will make the rotation value equal to 0turn hence we get a transition from .3turn to 0turn; the element is back to its initial position! Updating the value of --a will do nothing; it will be useful when you unhover.

When you unhover, the value of --i updates instantly from 0 to 1. Nothing will happen since --a is still equal to 0, which means the rotation is equal to 0 as well. Then, the transition of --a is triggered, moving it from 0turn to -100turn. We restart the “infinite” animation.

Do you get the trick? On hover, the variable --i will force the element to return to its initial position regardless of the actual rotation, and when you unhover, the animation starts again because we have set --a equal to 0, triggering the transition that simulates the infinite rotation.

You can also adjust the modulo based on your use case. We used 1turn since the element needs to make 1turn to get back to the initial position, but we can have more examples with different moduli.

And what about the opposite effect? You activate the animation on hover, and when you unhover, the element gets back to its initial position.

Here is the relevant code:

@property --a {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0turn; 
}
@property --i {
  syntax: "<number>";
  inherits: false;
  initial-value: 0; 
}
.box {
  rotate: calc(mod(var(--a),1turn)*var(--i));
  transition: --i .5s ease-out,--a 0s .5s;
}
.box:hover {
  --i: 1;
  --a: 10turn;
  transition: --i 0s,--a 10s linear;
}Code language: CSS (css)

Try to dissect the code as homework. Compare it with the previous implementation, and you will notice that I mainly switched a few values. We also don’t need to rely on @starting-style since we don’t need the infinite animation to run on page load.

Here is the effect applied to the glowing border:

Follow the Shortest Path!

Ready for a last effect? This time, when you unhover, the element will follow the shortest path to get back to the initial position.

The direction of the rotation will be different depending on the current position of the element when you un-hover.

To achieve this effect, we update the rotation formula from this:

rotate: calc(mod(var(--a),1turn)*var(--i));Code language: CSS (css)

to this:

rotate: calc((mod(var(--a),1turn) - (1 + sign(mod(var(--a),1turn) - .5turn))*.5turn)*var(--i));Code language: CSS (css)

If we omit the multiplication with the variable --i, here is the new addition to the formula:

(1 + sign(mod(var(--a),1turn) - .5turn))*.5turnCode language: CSS (css)

The mod() function gives us a value in the range [0turn 1turn] and the goal is to get back to 0turn on hover following the shortest path. To follow the shortest path, we have only two options: clockwise and counterclockwise.

Two options mean that we have two different ranges of values: [0turn .5turn] and [.5turn 1turn]. To make it easy to understand, let’s pick one value of each range and apply the formula.

For --a: .3turn we get:

rotate: calc((.3turn - (1 + sign(.3turn - .5turn))*.5turn)*var(--i));
rotate: calc((.3turn - (1 + sign(-.2turn))*.5turn)*var(--i));
rotate: calc((.3turn - (1 + -1)*.5turn)*var(--i));
rotate: calc(.3turn*var(--i));Code language: CSS (css)

When --i is set to 0, we get a transition from .3turn to 0turn.

For --a: .7turn we get:

rotate: calc((.7turn - (1 + sign(.7turn - .5turn))*.5turn)*var(--i));
rotate: calc((.7turn - (1 + sign(.2turn))*.5turn)*var(--i));
rotate: calc((.7turn - (1 + 1)*.5turn)*var(--i));
rotate: calc((.7turn - 1turn)*var(--i));
rotate: calc(-.3turn*var(--i));Code language: CSS (css)

When --i is set to 0, we get a transition from -.3turn to 0turn.

But the angle is no longer the same. How does it work?

It’s actually the same angle! -.3turn is equivalent to .7turn since the difference between them is 1turn. Instead of having a transition from .7turn to 0turn, which is the long path. I transform it to another angle closer to 0turn and in this case it’s -.3turn. That negative sign is what makes the element rotate in the opposite direction.

The formula looks a bit complex, but at the end it will subtract 1turn from all the angles in the range [.5turn 1turn] to place them in the range [-.5turn 0turn], which is closer to 0turn. The range [0turn .5turn] is not affected.

This last example is probably overkill, but it’s still a cool effect to implement with some modern CSS features. At the end, you don’t need to bother yourself with the formula. All you have to do is adjust the modulo variable to suit your use case.

.box {
  --t: 1turn; /* control the modulo */
  --d: .5s;   /* the transition */
  
  rotate: calc((mod(var(--a),var(--t)) - (1 + sign(mod(var(--a),var(--t)) - var(--t)/2))*var(--t)/2)*var(--i));
  transition: --i var(--d) ease-out,--a 0s var(--d);
}
.box:hover {
  --i: 1;
  --a: 10turn;
  transition: --i 0s,--a 10s linear;
}Code language: CSS (css)

And here is the effect applied to the glowing border:

Conclusion

That’s all for this second part. Now you have a lot of handy CSS tricks to control infinite animations. You probably won’t use them all, but it was a good opportunity to study some cool features, such as animation-composition@starting-style, and many math functions.

I leave you with a last demo to study. On hover, an infinite animation starts. On click, it gets faster. On unhover, the element snaps back to its initial position following the shortest path:

Article Series