close
Figured Shorthand CSS · Learning & build hub

Write shorthand.
Ship real CSS.

A hands-on home for the FSCSS ecosystem — the language itself, plus the modules built on top of it: charts, forms, progress rings, page shells, and 3D. Learn the syntax, then combine the modules into things that actually ship.

$ npm install fscss
10+modules in the ecosystem
~10kbCDN runtime
~0.5kbcompiled, per module
0required JS runtime
/* NEW in v1.1.25 — pattern() */
pattern(0.5: "Hello World card", `
  border-radius: 12px;
  padding: 24px;
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: #fff;
  box-shadow: 0 8px 24px rgba(0,0,0,.25);
`)

.card {
  hello world card
}
/* plain, browser-ready CSS */
.card {
  border-radius: 12px;
  padding: 24px;
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: #fff;
  box-shadow: 0 8px 24px rgba(0,0,0,.25);
}
New in v1.1.25 — describe styles in plain language; FSCSS matches by similarity.
What FSCSS actually is

A preprocessor that stays out of your way

FSCSS (Figured Shorthand CSS) compiles a shorthand dialect of CSS into plain, standard CSS — either ahead of time with the CLI, or live in the browser via a small runtime script. No build step is required to try it.

Variables & stores

Less repetition

Define $variables once and reuse them anywhere. Group repeated declarations into a named @fun store and apply the whole block with one line.

Reusable blocks

@define + pattern()

@define turns a block into a parameterized mixin. pattern() (new in v1.1.25) lets you describe styles in plain language — FSCSS matches by similarity and injects the CSS.

Two ways to ship

Compile or run live

Use the CDN runtime for prototyping — it compiles in-browser on load. Switch to the CLI for production and ship zero-runtime, plain .css instead.

Syntax primer

Enough FSCSS to read every example on this page

Seven pieces of syntax cover almost everything the modules below use — including the new pattern() from v1.1.25. Want the long version, with a full project built step by step? See the full tutorial.

Variables

Reusable values, resolved at compile time.

$primary-color: #2563eb;
.btn { background: $primary-color; }

@fun style stores

Group properties, apply the group by name.

@fun(card){ padding: 1.5rem; }
.card { @fun.card }

@define — parameterized

A mixin that takes arguments.

@define card(bg, fg){
  background: @use(bg);
  color: @use(fg);
}
.card { @card(#079, #ddd) }

pattern() — semantic match NEW

Describe styles in plain language; FSCSS matches by similarity.

pattern(0.6: "rounded primary button", `
  border: none; border-radius: 8px;
  background: #fff; color: #764ba2;
`)
.btn { rounded primary button }

@import — selective

Pull specific mixins from a module, or all of them.

@import((page-hero, page-btn) from customizable)
@import((*) from st-core)

@event — logic

Conditional values, resolved in CSS itself.

@event tone(v){
  if v <= 30 { return: #D69308 }
  el { return: #26FF00 }
}

@arr — arrays & loops

Generate a run of classes without hand-writing each one.

@arr steps[count(100)]
.p-@arr.steps[]{
  $v: @arr.steps[];
}
The module ecosystem

Top-Five modules around the philosophy

Each module solves one hard visual problem in pure CSS — data lives in custom properties, shape lives in clip-path, gradients, and transforms. JavaScript, where it appears at all, only ever writes a variable.

st-core.fscss

Charts and dashboards, zero JS charting library

Line charts, area fills, grids, axes, and stat cards built entirely from clip-path: polygon() and eight CSS custom properties (--st-p1--st-p8). Update a chart at runtime by writing a variable — the browser repaints the shape natively, no redraw.

@st-root @st-chart-line @st-chart-fill @st-chart-dots @st-stat-card @st-cat-bar-fill
import
@import((*) from st-core)
@st-root()
@st-chart-fill(.chart-fill)
@st-chart-line(.chart-line)
st-core.fscss dashboard example
form.fscss

Modern form interactions, no form library

Floating labels run on :placeholder-shown. Checkboxes, radios, and a switch use the checkbox-hack with a hand-drawn checkmark from two rotated borders — no icon font, no SVG. Validation states toggle with one class name.

@form-root @form-float @form-checkbox @form-switch @form-validation @form-btn-primary
import
@import((*) from form)
@form-root()
@form-float(.form-group, .form-input, .form-label)
@form-btn-primary(.form-btn-primary)
form.fscss sign-up card example
circle-progress.fscss

A progress ring that decides its own color

JavaScript only ever writes one value — a percentage class name. Everything visual, including which color a given value should glow, is decided inside FSCSS itself with @event conditional logic and an @arr loop that generates every state from 0–99 in advance.

@progress-root @circle-progress @progress-range @progress-animate @event
import
@import((*) from circle-progress)
@progress-root()
@circle-progress(#progress[class^='p-'])
circle-progress.fscss ring states
customizable.fscss

The recurring page shapes, as independent pieces

Nav, hero, feature grid, CTA banner, footer, 404, and a full long-form typography scale — each its own mixin, imported only when a page actually needs it. One token layer, written by page-root, drives color and radius across every piece at once.

@page-root @page-hero @page-btn-primary @page-404 @page-prose
import
@import((page-root, page-hero, page-btn) from customizable)
@page-root()
@page-hero(.page-hero)
customizable.fscss page shell example
cube.fscss

Real 3D, six faces, decoupled from content

Six absolutely-positioned faces on a preserve-3d parent, pushed out by half the cube's edge and rotated to face outward. Face position and face content are separate concerns — apply any of eight "micro" effects (fire, matrix rain, glass, holo, glitch) to any face independently.

@cube-wrapper @cube-face-front @cube-size @cube-micro-glass @cube-micro-dice
import
@import((*) from cube)
@cube-root()
@cube-wrapper(.my-cube)
@cube-face-front(.my-cube .f1)
cube.fscss rotating dice example
Combining modules

Building something real, not five separate demos

Every module reads its own tokens and stays out of the others' way, so nothing stops them sharing one page. Here's what a real interface looks like once they're stacked together — a creator dashboard: st-core renders the earnings chart, circle-progress tracks a payout goal, form.fscss handles the withdrawal request, customizable.fscss provides the page shell, and a small cube.fscss badge marks a milestone. The full walkthrough, file by file, is in the tutorial.

Real build pattern
  1. 01 customizable.fscss lays down the page shell — nav, container, token layer — so every other module inherits the same spacing and radius scale.
  2. 02 st-core.fscss renders the earnings-over-time chart and the stat card up top, fed by whatever your backend returns.
  3. 03 circle-progress.fscss shows progress toward the next payout threshold — one class name, no manual color logic.
  4. 04 form.fscss handles the "Request withdrawal" form — floating label, validation state, submit button.
  5. 05 cube.fscss adds a small rotating badge when a creator hits a milestone — a detail, not the centerpiece.
combined import
@import((page-root, page-base) from customizable)
@import((*) from st-core)
@import((*) from circle-progress)
@import((form-root, form-group, form-input,
         form-label, form-float, form-btn-primary) from form)
@import((cube-root, cube-wrapper, cube-face-front,
         cube-micro-glass) from cube)
Combined dashboard build example
Sponsors & supporters

Who keeps FSCSS moving

FSCSS is maintained in the open, alongside the products that depend on it.

Install it, import a module, build something real

Start with the CDN runtime for prototyping, then compile to plain CSS when you're ready to ship.