This snippet builds a stepped “processing 0% → 99% → done” animation by looping an array into @keyframes percentages — not a JS timer.
Setup
npm install -g fscss@latest- VS Code: FSCSS language support (FSCSS Support)
- File:
my-first-fscss.fscss→ compile or runtime-load
Source (your idea, tightened)
h2::after {
content: "...";
animation: count 10s steps(100) forwards;
}
/* 1, 2, … 99 (auto list for keyframe stops) */
@arr numlist[count(99)]
@define counter(start:ing..., process:ing..., end:ed){`
0% {
content: "@use(start)0%";
}
@arr.numlist[]% {
content: "@use(process)@arr.numlist[]%";
}
100% {
content: "@use(end)";
}
`}
@keyframes count {
@counter(Processing..., Processing..., Processed)
}
What “auto-loop” is here
| Piece | Role |
|---|---|
count(99) |
Builds a numeric list used as 1–99 (engine: count(n) / count(n, 1) → index list). |
@arr numlist[…] |
Stores that list. |
@arr.numlist[] |
Auto-index: expand once per item. |
@arr.numlist[]% |
Each item becomes a keyframe selector: 1%, 2%, … 99%. |
@define counter(…) |
Template for the keyframe body; `@use(start |
{% raw %}@counter(…) inside @keyframes
|
Injects the whole ladder into count. |
So the loop is compile-time expansion, not for in the browser.
Breakdown
1. Target
h2::after {
content: "...";
animation: count 10s steps(100) forwards;
}
- Animates
contenton the pseudo-element. -
steps(100)≈ one visual step per percent over 10s. -
forwardskeeps the finalProcessedtext.
2. Index array
@arr numlist[count(99)]
Same family as modules indexes: a list long enough to drive stops. Here each value is also the percentage number in the output.
3. Reusable keyframe block
@define counter(start:…, process:…, end:…){` … `}
-
0%— intro label +0%. -
@arr.numlist[]%— for eachninnumlist, emit:- selector:
n% -
content: "<process>n%"
- selector:
-
100%— final label only (e.g.Processed).
4. Wire into a named animation
@keyframes count {
@counter(Processing..., Processing..., Processed)
}
Expands to a long @keyframes count { … } with ~100 content stops.
Shape of compiled CSS (illustrative)
Exact quoting depends on the compiler; structure is:
h2::after {
content: "...";
animation: count 10s steps(100) forwards;
}
@keyframes count {
0% {
content: "Processing...0%";
}
1% {
content: "Processing...1%";
}
2% {
content: "Processing...2%";
}
/* … */
99% {
content: "Processing...99%";
}
100% {
content: "Processed";
}
}
That is the auto-loop: one array walk → many keyframe rules.
Example HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>FSCSS auto-loop counter</title>
<script src="https://cdn.jsdelivr.net/npm/fscss@1.2.4/runtime.min.js" async></script>
<link type="text/fscss" href="my-first-fscss.fscss">
<!-- or: <link rel="stylesheet" href="my-first-fscss.css"> after CLI -->
<style>
body {
font-family: system-ui, sans-serif;
padding: 2rem;
background: #0f172a;
color: #e2e8f0;
}
h2 {
font-size: 1.25rem;
font-weight: 600;
}
h2::after {
margin-left: 0.35em;
color: #38bdf8;
}
</style>
</head>
<body>
<h2>Status</h2>
<!-- ::after shows Processing...0% → … → Processed -->
</body>
</html>
Compile
fscss my-first-fscss.fscss my-first-fscss.css
Mental model
count(99) → list of stops
@arr.x[]% → “for each item, emit item% { … }”
@define → reuse labels (start / process / end)
@keyframes → holds the expanded ladder
Auto-loop = array auto-index used as keyframe percentages (or selectors elsewhere), so one definition drives N rules.
Variants
- Progress label only: change
@use(process)strings. - Fewer steps:
count(20)+ shorter animation /steps(20). - Same pattern for staggered selectors:
.item-@arr.idx[] { animation-delay: … }(as in arrays docs).
Loop the array at compile time; the browser only plays the keyframes.
Top comments (2)
I love how you've utilized an array to generate keyframes for the FSCSS auto-loop animation, creating a seamless "processing" effect. This approach reminds me of my own experiences with using data-driven animations in UI design. Have you explored using similar techniques for other types of animations, such as progress bars or loading indicators?
Thanks! Yes, same idea works for stepped progress bars (width at
@arr.steps[]%) and for intros that set a--progress-*variable each step. Smooth bars can stay a single keyframearrays help most when you want many discrete steps or a label + bar in sync. Circle-style loaders often use one CSS variable updated live
compile-time arrays still help for scripted 0–100 sequences.