DEV Community

FSCSS tutorial
FSCSS tutorial

Posted on • Originally published at github.com

Introducing customizable.fscss - a pure CSS page-styling system

Every site ends up rebuilding the same handful of pages: a landing page, a 404, a terms page, an about page, a blog post. Different content, same underlying shapes — a nav bar, a heading with supporting text, some cards, a closing call to action, a footer. customizable.fscss is a pure CSS module for exactly that: the recurring page structure, built once, reused everywhere it's needed, with nothing forced on a page it doesn't use.

<script src="https://cdn.jsdelivr.net/npm/fscss@1.1.24/exec.min.js" defer></script>

<style>
@import((page-root, page-base, page-hero, page-btn, page-btn-primary) from customizable)

@page-root()
@page-base(body)
@page-hero(.page-hero)
@page-btn(.page-btn)
@page-btn-primary(.page-btn-primary)
</style>

<section class="page-hero">
  <h1>A modern landing page, built entirely in CSS</h1>
  <p>Swap the copy, drop in your own images, and it adapts down to any screen size.</p>
  <a href="#" class="page-btn page-btn-primary">Get started</a>
</section>
Enter fullscreen mode Exit fullscreen mode

Just CSS mixins compiled by FSCSS.

The core idea: components, not a template

Most page kits hand you one fixed layout and expect you to delete the parts you don't want. customizable.fscss works the other way — each piece is its own independent mixin, and a page imports only what it actually uses:

@import((page-root, page-base, page-404, page-btn, page-btn-primary) from customizable)
Enter fullscreen mode Exit fullscreen mode

That's the entire import for a 404 page. No hero styles, no feature grid, no footer columns compiled in for a page that will never render them. A full marketing landing page pulls in more:

@import((*) from customizable)
Enter fullscreen mode Exit fullscreen mode

Same module, two completely different outcomes, because the selection list decides what actually ships.

What's in it

  • Navigation — sticky, blurred on scroll, wraps its links on narrow screens instead of overflowing
  • Hero section — fluid heading size via clamp(), action buttons that stack full-width on mobile
  • Badge — a small pill with a glowing dot, for "now live" or version announcements
  • Images — three related mixins: page-img for general content images, page-hero-image for a larger screenshot/mockup below the hero copy, page-figure for an image-plus-caption pair inside long-form content
  • Buttons — a shared base plus primary/ghost variants
  • Feature grid — auto-reflowing cards, collapses to one column on mobile
  • CTA banner — a closing statement with its own gradient background
  • Footer — split into a multi-column link grid and a separate copyright bar, so a page can use either independently
  • 404 page — fills the viewport, centers itself, no dependency on anything else on the page
  • page-prose — a full typography scale for long-form content: terms of service, about pages, blog posts

One token layer drives everything

Every color, radius, spacing value, and font comes from a single set of CSS custom properties, written once by page-root:

@page-root()

:root {
  --page-accent: #0fcbe8;
  --page-radius: 12px;
}
Enter fullscreen mode Exit fullscreen mode

Because every component reads from these variables instead of hardcoded values, that two-line override changes the accent color across the navigation, badges, buttons, and CTA banner at once. No hunting through component definitions to restyle a brand.

Responsive by default, not by afterthought

Every structural mixin carries its own breakpoint at 640px, written inside the mixin itself rather than as a separate stylesheet bolted on later. That means the responsive behavior travels with the component the moment it's imported — a page doesn't need to reimplement mobile handling for something it just pulled in. Stacked hero buttons, single-column feature grids, wrapped navigation links, and a reduced-column footer all come included.

Try it

<script src="https://cdn.jsdelivr.net/npm/fscss@1.1.24/exec.min.js" defer></script>
<style>
  @import((*) from customizable)
</style>
Enter fullscreen mode Exit fullscreen mode

Or compile ahead of time with the CLI for zero runtime dependency:

npm install -g fscss
fscss page.fscss page.css
Enter fullscreen mode Exit fullscreen mode

Full documentation, every component's markup, the complete token reference, and known limitations are in the README: github.com/fscss-ttr/customizable.fscss

If a page type you build often isn't covered here, say so — that's usually where the next addition to the module comes from.

open-source: https://github.com/fscss-ttr/customizable.fscss

MIT License

Top comments (0)