We Need to Talk About Keyframes 🤦
CSS animations are genuinely fun — right up until you need to animate something that counts, steps, or cycles through a list.
You know the moment. You're building a loading indicator, a progress bar, or a sequenced visualization, and then it hits you:
@keyframes progress {
0% { content: "0%"; }
1% { content: "1%"; }
2% { content: "2%"; }
/* ... please send help ... */
100% { content: "100%"; }
}
That's over a hundred lines of CSS to do something a for loop handles in two seconds. Reviewing this in a PR? Painful. Modifying it six months later? Even worse.
The instinct is to offload this to JavaScript — but JS adds complexity, and if you're not careful with how you update the DOM, you'll end up causing layout thrashing that hurts your page's rendering performance.
What if CSS itself could just... loop?
FSCSS: A Pre-Processor Built for This Exact Problem 🛠️
FSCSS — short for Figured Shorthand Cascading Style Sheet — is a CSS pre-processor with one core mission: eliminate repetitive animation code.
Where Sass and Less focus broadly on making CSS more programmable, FSCSS is laser-focused on keyframe generation. It brings three new ideas to your stylesheet:
- 🗂️ Value arrays — group ranges or lists of values under a name
- 🔄 Loop syntax — iterate over those arrays directly inside
@keyframes - 🧮 Auto-calculation — the compiler handles all the percentage math
Write less. Generate more. Ship cleaner code.
How It Actually Works
The old way — writing it all out by hand
@keyframes countUp {
0% { content: "0%"; }
1% { content: "1%"; }
/* this goes on forever */
100% { content: "100%"; }
}
The FSCSS way — let the compiler handle it
@arr numlist[count(100)];
@keyframes countUp {
@arr.numlist[]%{
content: "@arr.numlist[]";
}
}
You define the array with @arr, loop over it, and reference the current value for each blog. The compiler does the expansion and spits out a complete, browser-ready CSS file. Clean input, correct output, no manual counting.
Three Solid Reasons to Add This to Your Toolkit
🔧 1. Changes Take Seconds, Not Hours
Requirements shift. A loader that counts to 100 today might need to count to 500 tomorrow — or jump in increments of 10 instead of 1. In plain CSS, that's a full rewrite.
| Change Needed | Standard CSS | FSCSS |
|---|---|---|
| Extend range to 500 | Rewrite everything | Edit one number |
| Switch to 10-step increments | Start over | Edit one number |
| Swap out a value | Hunt through the file | Update the @arr
|
One-line edits. Recompile. Done.
⚡ 2. Zero JavaScript, Full CSS Performance
Because the output is pure CSS, your animations run directly on the browser's rendering engine. The JavaScript thread stays completely untouched — free to handle the logic that actually needs it. Smoother animations, better frame rates, cleaner architecture.
🗜️ 3. Tiny Source, Compressible Output
Yes, the compiled CSS file can get large with hundreds of keyframes. But repetitive text compresses extremely well — Gzip was practically made for this kind of output. Your users download a fraction of the raw file size, while you maintain a source file that's small enough to read in under a minute.
Setting It Up
You'll need Node.js on your machine before anything else.
Step 1 — Install globally via npm
npm install -g fscss
Step 2 — Write your source file
Create styles.fscss and write your animation logic using FSCSS syntax.
Step 3 — Compile to standard CSS
fscss styles.fscss styles.css
The resulting styles.css is completely valid, framework-agnostic CSS. Drop it anywhere.
A Practical Example: Animating Through a Color Palette
Say you want an element to transition through four brand colors over the course of an animation:
@arr palette[#e63946, #457b9d, #2a9d8f, #e9c46a];
@keyframes brandCycle {
@arr.palette[]%{
background-color: @arr.pelette[];
}
}
FSCSS figures out that four values need four evenly-spaced stops — 0%, 33%, 66%, 100% — and generates the corresponding CSS automatically. Add more colors to the array, and it recalculates everything on the next compile.
Quick Comparison
| Vanilla CSS | FSCSS | |
|---|---|---|
| 100-step animation | 100+ lines | ~5 lines |
| Updating the range | Full rewrite | Edit 1 value |
| Needs JavaScript | Optional | Nope |
| Runtime performance | CSS engine | Same (CSS engine) |
| Source readability | 😵 | 😌 |
Final Thought
Frontend tooling has gotten incredibly sophisticated on the JavaScript side. Our CSS tooling deserves the same love — especially for animations, which are often the most repetitive part of any stylesheet.
FSCSS doesn't try to replace Sass or reinvent CSS. It just solves one specific, painful problem really well.
Give your keyframes a break. Let the compiler earn its keep.
What's the most absurd keyframe block you've ever had to write? Share it below — bonus points if it made a coworker visibly uncomfortable 👇

Top comments (2)
Had 0 idea about this, great article
Thank you,
you can learn more about this by visiting GitHub github.com/fscss-ttr/FSCSS