DEV Community

FSCSS tutorial
FSCSS tutorial

Posted on

Building a Smart Circular Progress with FSCSS + JavaScript (Interactive Demo)

There’s something oddly satisfying about watching a progress circle fill up.

But most implementations today are either:

heavily JavaScript-driven, or

purely CSS with limited flexibility

So something different.

What if:

JavaScript only controls the value

and FSCSS handles everything visual — including logic?

The result is a small demo… but it reveals a much bigger idea.


What We’re Building

An interactive circular progress that:

  • updates with a range slider

  • changes color dynamically based on value

  • animates smoothly

  • keeps logic separated between JS and FSCSS

👉 JS = state
👉 FSCSS = styling + logic


Setup


Step 1: Import the Progress

@import((*) from circle-progress)

@progress-root()
@circle-progress(#progress[class^='p-'])
Enter fullscreen mode Exit fullscreen mode

This connects FSCSS to any class like .p-50, .p-80, etc, with id='progress'.


Step 2: Add Dynamic Color Logic

@event range-color(range){
    if range <=10{
        return: #C86433
    }
    el-if range <= 30{
        return: #D69308
    }
    el-if range <= 45{
        return: #A1AC1C
    }
    el-if range <= 60{
        return: #86CA1A
    }
    el-if range <= 80{
        return: #1CAC52
    }
    el-if range <= 95{
        return: #13B046
    }
    el{
        return: #26FF00
    }
}
Enter fullscreen mode Exit fullscreen mode

Instead of hardcoding colors per class, we define a rule system.


Step 3: Generate All Progress States

@arr p-ranges[count(100)]
.p-0{
    $range: 0;
    @progress-range($range)
    --progress-color-glow: @event.range-color($range);
    --progress-color-arc: @event.range-color($range);
}
.p-@arr.p-ranges[]{
    $range: @arr.p-ranges[];
    @progress-range($range)
    --progress-color-glow: @event.range-color($range);
    --progress-color-arc: @event.range-color($range);
}
Enter fullscreen mode Exit fullscreen mode

This generates .p-0 → .p-99 automatically.

No manual classes. No repetition.


Step 4: Add Polish

#progress {
    border-radius: 50%;
    box-shadow: 0 0 20px var(--progress-color-glow);
    transition: all 0.3s ease;
    @progress-animate(4s)
}
Enter fullscreen mode Exit fullscreen mode

Now we have:

glow effect

smooth transitions

animated progress


Step 5: JavaScript (Minimal)

const rangeInp = document.getElementById('range');
const progress = document.getElementById("progress");

rangeInp.addEventListener('input', e=>{
    const percent = Math.min(Math.round(e.target.value), 100);
    progress.className = `p-${percent}`;
    progress.textContent = `${percent}%`;
});
Enter fullscreen mode Exit fullscreen mode

That’s it.

No styling logic in JS.


This demo shows a subtle but important pattern:

Traditional approach:

JS controls everything (state + style)

This approach:

  • JS → updates value

  • FSCSS → decides appearance using logic

That means:

  • cleaner separation

  • reusable styling logic

  • less JS complexity


Live Demo

CodePen:


It’s just a demo…

But it hints at something bigger:

CSS is no longer just styling — it can think.

And when you combine that with JavaScript correctly,
you don’t get more complexity…

You get clarity.


Top comments (0)