Up until v1.2.0, FSCSS syntax fully resolved inside <style> blocks. Inline style attributes were mostly just... inline CSS, the regular kind.
That changed in v1.2.0. Boot now processes every element's style attribute the same way it processes a <style> block. Same compiler, same pipeline, same @define mixins, same arrays. The practical result: you can call a mixin straight from an attribute, and combined with the JS API, you can recompile it on the fly.
Here's what that looks like, and why it's more useful than "less typing."
The setup
<script src="https://cdn.jsdelivr.net/npm/fscss@1.2.0/runtime.min.js" async></script>
<style>
@define btn-style(bg: #636EE7){
padding: 10px 20px;
color: color-mix(#dddddd, @use(bg));
background: @use(bg);
border: 2px solid;
border-radius: 25px;
font-weight: 700;
}
</style>
<button style="@btn-style(#1a2a4f)">Search</button>
<button style="@btn-style(#f00f00)">Search</button>
<button style="@btn-style(#4f4f4f)">Search</button>
One @define block, declared once. Three buttons, each calling it with a different color. No repeated class names, no utility soup, no separate stylesheet just to vary one property per element. On boot, FSCSS walks every style attribute, runs it through the same compiler that processes <style> blocks, and writes the compiled CSS back in place.
Where it gets interesting: dynamic updates
Inline processing on its own is a nice shorthand. Paired with the JS API, it becomes something closer to a lightweight styling engine.
<button style="
@arr colors[#1E2783, #8C29B2, #C41348, #0098d0]
@btn-style(@arr.colors!.randint)
" onclick="update(this)">Click</button>
<script>
const update = async (btn) => {
const newStyle = await xfscss.process("@btn-style(@arr.colors!.randint)");
btn.setAttribute("style", newStyle);
};
</script>
Click the button, and xfscss.process() recompiles @btn-style(@arr.colors!.randint) on demand, picking a fresh random color from the array each time. The style attribute gets swapped out, no rewritten CSS, no framework state, no manual color logic in JavaScript. FSCSS just runs again.
The part that trips: the array is still there
Once boot processes that button's style attribute, the visible result is just the compiled declarations. The @arr colors[...] line is gone from the DOM, cleaned up along with the rest of the FSCSS source.
But the array itself was registered during that processing pass, not just written to that one attribute. So it's still resolvable afterward. That's the whole reason the click handler above works: @arr.colors!.randint keeps returning a valid color long after the line that declared it has disappeared from the page.
It's a small detail, but it's what makes inline processing genuinely useful for interactivity rather than a one-shot trick.
module mixins work the same way
Since boot doesn't treat style attributes as a special case, anything you can call inside a <style> block, including mixins from imported modules, works inline too:
<div class="chart-line line-2" style="background: #E8A030; @st-chart-points(10, 20, 16, 15, 66, 50, 80, 54)"></div>
That's an st-core chart mixin, called from an inline attribute, resolving exactly as it would from a stylesheet.
runtime.js or esm.js?
If you want this working automatically, runtime.js is the right entry point. It boots, processes every <style> block and style attribute on the page, and still exposes xfscss globally so you can call process() yourself afterward, exactly like the click handler above.
esm.js is a better fit when you want the compiler as a tool rather than something running against a live page, an FSCSS-to-CSS conversion utility, or a custom pipeline that decides what gets processed and when. It never touches the DOM unless you call reboot(), run(), or process() yourself.
Try it
<script src="https://cdn.jsdelivr.net/npm/fscss@1.2.0/runtime.min.js" async></script>
Resources:
API References fscss.devtem.org/api
Docs: fscss.devtem.org/docs
GitHub: github.com/Figsh/xfscss


Top comments (0)