Designers and developers making animated cursors for Windows
Animated cursors explained: .ani files, frames and jiffies
An .ani file is a stack of ordinary cursor images plus a little timing information. Once you know how frames, steps and jiffies fit together, you can make animated cursors that play at the speed you meant.
What an .ani file is
.ani is the Windows animated cursor format. Windows uses it for its own Busy and Working in Background cursors (aero_busy.ani and aero_working.ani).
Inside, an .ani file is a RIFF container, the same family of format as WAV and AVI. It holds:
- a short header that says how many frames there are and how fast to show them;
- the frames themselves, each one a complete
.cur(or.ico) file with its own images and hotspot; - optionally, a per-step timing list and a play order.
Step 1: Learn the parts of the file
| Chunk | Required | What it holds |
|---|---|---|
RIFF with form type ACON | yes | The container for everything else |
LIST of type INFO | no | A title (INAM) and an author (IART) as text |
anih | yes | The header: frame count, step count, default speed, flags |
rate | no | One display time per step, in jiffies |
seq | no | One frame number per step: the play order |
LIST of type fram | yes | One icon chunk per frame, each a full .cur or .ico file |
Every chunk is a four-letter name, a four-byte length and the data. Chunks with an odd length get one padding byte so the next chunk starts on an even byte.
Step 2: Read the anih header
The anih chunk is 36 bytes: nine four-byte numbers, least significant byte first.
| Field | Meaning |
|---|---|
cbSize | The size of this header: always 36 |
nFrames | How many frames are stored in the fram list |
nSteps | How many steps one loop of the animation has |
iWidth, iHeight | Frame size. Left at 0 when the frames are cursor files, which carry their own sizes |
iBitCount, nPlanes | Colour depth, also unused when the frames are cursor files |
iDispRate | The default time each step stays on screen, in jiffies |
bfAttributes | Flags: 1 means the frames are icon or cursor files, 2 means a seq chunk is present |
The Windows Busy cursor, for example, has 18 frames, 18 steps, a rate of 3 jiffies and the flags set to 1.
Step 3: Get the timing right with jiffies
A jiffy is one sixtieth of a second, about 16.7 milliseconds. Every speed in an .ani file is a whole number of jiffies.
| Jiffies per step | Milliseconds | Frames per second |
|---|---|---|
| 1 | 16.7 | 60 |
| 2 | 33.3 | 30 |
| 3 | 50 | 20 |
| 4 | 66.7 | 15 |
| 5 | 83.3 | 12 |
| 6 | 100 | 10 |
| 10 | 166.7 | 6 |
| 12 | 200 | 5 |
| 30 | 500 | 2 |
| 60 | 1000 | 1 |
To work out a loop’s length, add up the steps: 18 steps at 3 jiffies each is 54 jiffies, 0.9 seconds, which is the Windows Busy spinner.
iDispRate sets one speed for every step. Add a rate chunk when steps need different speeds, for example a pause on the first frame: it lists one jiffy count per step and overrides iDispRate.
Step 4: Reuse frames with a sequence
Steps and frames are not the same thing. Frames are the images stored in the file; steps are what plays. A seq chunk lists which frame to show at each step, so you can reuse frames without storing them twice.
A swinging animation with six frames (0 to 5) that plays forward and back could use ten steps: 0 1 2 3 4 5 4 3 2 1. Set nFrames to 6, nSteps to 10, add the seq chunk and set the flag value to 3 (1 plus 2).
Step 5: Keep the hotspot steady
Each frame is a full cursor file, so each frame stores its own hotspot. Give every frame the same hotspot. If they differ, the click point jumps around as the animation plays, and people miss what they aim at.
The same goes for the shape’s position: keep the pointing tip on the same pixel in every frame and animate only the decoration around it, the way the Working in Background cursor keeps its arrow still while the ring spins.
Step 6: Store several sizes in every frame
Because each frame is a .cur file, each one can hold several sizes. The default Windows animated cursors store 32, 48 and 64 pixel versions in every frame, so they stay sharp when someone enlarges their pointer. Use the same set of sizes in every frame.
Step 7: Make and test one
- Draw your frames at 32x32 (and larger sizes if you can), with the hotspot on the same pixel in each.
- Put them together in the frames to ANI converter and set the speed in jiffies.
- On Windows, open Mouse Properties, select Busy or Working in Background on the Pointers tab, click Browse and pick your file. The Windows 11 install guide walks through it.
Animated cursors on websites
Browsers do not play .ani files. Old versions of Internet Explorer accepted them in CSS, but no current browser does, and an animated GIF set with url() shows a single frame. For movement on a website, use an element that follows the pointer, such as the dot and ring follower.
FAQ
How many frames should an animated cursor have?
Enough to look smooth at your speed and no more. The Windows spinners use 18 frames at 20 frames per second. Simple pulses and blinks often need only 4 to 8.
Why does my .ani play too fast or too slow?
The rate is in jiffies, not milliseconds. A rate of 100 means 100 sixtieths of a second, almost two seconds per step. Divide the milliseconds you want by 16.7 and round.
Can I turn an animated GIF into an .ani?
Yes. Split the GIF into frames and convert each delay to jiffies. GIF delays are stored in hundredths of a second, so multiply by 0.6 and round: a 10 (100 ms) delay becomes 6 jiffies.