Introduction to FSCSS @import

RECOMMENDED

The @import method in FSCSS allows you to bring one .fscss file (or selected parts of it) into another. This gives your project a modular structure, where each file focuses on a single task (variables, mixins, components, utilities…).

Think of @import as connecting puzzle pieces: you make small, clean pieces of code and then combine them into a full stylesheet. This makes your styles easier to read, maintain, and reuse.

Modular Architecture

Split styles into logical, focused files

Reusability

Use modules across multiple projects

Team Collaboration

Multiple developers can work simultaneously

Selective Imports

Import only what you need with aliases

Best Practice: Use @import to organize your styles into logical groups (variables, mixins, buttons, layouts). This way you avoid one giant stylesheet that's hard to manage.

Modern Import Syntax (v1.1.16+ / v1.2.0)

Selective Import with Aliases

Recommended

The preferred way to import is the selective form. You can pick exactly which exports you need and give them short aliases.

FSCSS
/* Import selected pieces from a module library and give them short names */
@import((
  circle-progress as clp,
  progress-range as pr,
  progress-root as p-root
) from circle-progress)

/* Now use the aliases */
@p-root()
@clp(.progress-circle)

.p72 {
  @pr(72)
}

This is the same pattern used by the official modules in fscss-modules.

Under the hood the pipeline runs three related stages (in order): impSel (pick / selective), impFrom (from), and procImp (full import). You can disable any of them with exec.obj.block(f import), exec.obj.block(f import pick), or exec.obj.block(f import from).

Step 1 — Create Your Modules

Organize Code into Focused Files

@import

Start by creating small, focused FSCSS files. For example:

  • _variables.fscss → all colors, spacing, and sizes
  • _mixins.fscss → reusable functions like flex-center
  • _buttons.fscss → consistent button styles

_variables.fscss

_variables.fscss
/* Color Variables */
$primary: #3b82f6;
$secondary: #7c3aed;
$accent: #06b6d4;
$dark: #0f172a;
$light: #f8fafc;

/* Spacing Variables */
$spacing-sm: 0.5rem;
$spacing-md: 1rem;
$spacing-lg: 2rem;

/* Typography */
$font-main: 'Inter', sans-serif;
$font-heading: 'Inter', sans-serif;

_mixins.fscss

_mixins.fscss
/* Flex Center Mixin */
str(flexCenter, "
  display: flex;
  justify-content: center;
  align-items: center;
")

/* Card Style Mixin */
str(cardStyle, "
  padding: $spacing-md!;
  border-radius: 8px;
  background: $light!;
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
")

/* Responsive Breakpoint Mixin */
str(respond-to, "
  @media (min-width: $breakpoint!) {
    @content;
  }
")

_buttons.fscss

_buttons.fscss
/* Base Button */
.button {
  padding: $spacing-sm! $spacing-md!;
  border-radius: 4px;
  font-weight: 600;
  transition: all 0.3s ease;
  border: none;
  cursor: pointer;
}

/* Primary Button */
.btn-primary {
  background: $primary!;
  color: white;

  &:hover {
    background: darken($primary!, 10%);
  }
}

/* Secondary Button */
.btn-secondary {
  background: $secondary!;
  color: white;

  &:hover {
    background: darken($secondary!, 10%);
  }
}

Project Structure

styles/
_variables.fscss
_mixins.fscss
_buttons.fscss
main.fscss

Step 2 — Import Modules in Main File

Combine Modules with @import

@import(exec(...))

Create a main.fscss file where you gather everything. You can still use the classic form:

main.fscss (classic)
/* Import Core Modules */
@import(exec(_variables.fscss))
@import(exec(_mixins.fscss))
@import(exec(_buttons.fscss))

/* Custom Styles */
body {
  background: $light!;
  color: $dark!;
  font-family: $font-main!;
  line-height: 1.6;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 $spacing-md!;
}

.card {
  cardStyle
  margin-bottom: $spacing-md!;

  .card-title {
    font-size: 1.5rem;
    color: $primary!;
    margin-bottom: $spacing-sm!;
  }
}

.centered {
  flexCenter
  height: 100vh;
}

Or the modern selective form (preferred when the module exports multiple pieces):

Selective import
@import((
  flexCenter as center,
  cardStyle as card
) from "_mixins.fscss")

.hero {
  @center
  height: 80vh;
}

.panel {
  @card
}
Card Title

This is a card with imported styles.

Step 3 — Link Main File in HTML

Connect FSCSS to Your HTML (v1.2.0)

HTML Integration

Finally, link main.fscss inside your HTML page. With the new runtime entry point the compiler automatically processes everything.

Note: Runtime mode is perfect for development and demos. For production, compile with the CLI (fscss main.fscss main.css) so the page ships pure CSS.
index.html (v1.2.0+)
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>FSCSS Modular Example</title>

  <!-- Link your main FSCSS file -->
  <link type="fscss" href="main.fscss">

  <!-- New v1.2.0 + runtime (auto-runs) -->
  <script src="https://cdn.jsdelivr.net/npm/fscss@1.2.6/runtime.min.js" async></script>
</head>
<body>
  <div class="container">
    <div class="card">
      <h2 class="card-title">Card Title</h2>
      <p>This is a card with imported styles.</p>
      <button class="button btn-primary">Primary Button</button>
      <button class="button btn-secondary">Secondary Button</button>
    </div>
  </div>
</body>
</html>

Prefer full control? Use the ESM build instead:

ESM (manual)
<script type="module">
  import xfscss from "https://cdn.jsdelivr.net/npm/fscss@1.2.6/esm.min.js";
  await xfscss.reboot();   // processes all <link type="fscss"> and <style>
</script>

Advanced @import Usage

Powerful Import Patterns

Advanced Features

Explore advanced patterns for organizing and importing your FSCSS modules.

Nested Imports

You can import files inside other files for deep modularity.

/* components.fscss */
@import(exec(_buttons.fscss))
@import(exec(_cards.fscss))
@import(exec(_navigation.fscss))

Selective + Alias

Import only the pieces you need and rename them.

@import((
  primaryBtn as btn,
  secondaryBtn as btn2
) from "my-buttons.fscss")

.cta { @btn }
.alt  { @btn2 }

With Events / Themes

Combine @import with events for dynamic loading.

@import(exec(_init themes))

div.star {
  background: @event.theme(forest);
  $box-size: 200px;
  %2(width, height[: $box-size!;])
  tr Shape: @event.shape(star);
}
Warning: Avoid circular imports (file A imports file B, and file B imports file A). This can cause infinite loops and break processing.

Controlling the Import Pipeline

exec.obj.block for imports

You can selectively disable import processing stages when needed (debugging, special builds, etc.):

FSCSS
/* Skip all import handling */
exec.obj.block(f import);

/* Or skip only selective / from stages */
exec.obj.block(f import pick);
exec.obj.block(f import from);

All exec.obj.block(...) markers are stripped from the final CSS.

v1.2.6+ — Chained imports & dependency @define

How dependencies resolve

1.2.6

From FSCSS 1.2.6, the import graph is resolved fully before your file finishes compiling.

  • Chained imports resolve fully. If c imports b and b imports a, b’s imports are resolved first so everything arrives in c’s output. Works for both * and named imports.
  • Relative paths resolve against the importing file. ./a.fscss inside b is read relative to b, not the page or the process cwd. Same rule for local files and remote URL bases.
  • Named imports carry their dependencies. Importing foo also brings any @define that foo calls, and anything those call in turn. Carried dependencies keep their original names, even when foo is imported with an alias.
  • Output is inserted as written. $ sequences in imported code ($&, $1, etc.) are not reinterpreted.
Alias + carried dependencies
@import((foo as my-foo) from "./b.fscss")

/* Output includes:
   - @define my-foo(...)   (aliased export)
   - @define blocks that foo depends on, under their ORIGINAL names
*/
Known limitation: a carried dependency can clash with a @define of the same name already in the importing file. Prefer selective imports and unique prefixes in shared modules.

Rename with as — file ownership

Original name is undefined in this file

as fully renames the binding for the current file. No re-@define wrapper is required to pass names along in 1.2.6+: a file owns the names it imported; the next file can import those owned names.

style.fscss
@import((mirror as m) from fscss:micros)
app.fscss
@import((m as mirr) from "style.fscss")
@mirr(colors, indices)   /* ✅ */
/* @m / @mirror          ❌ undefined in app */

See also Modular system and @define.

Import forms (quick reference)

FSCSS
/* Named + alias */
@import((circle-progress as cp, progress-range as pr) from circle-progress)

/* Everything */
@import((*) from "animations.fscss")

/* Registry (no quotes) */
@import((*) from st-core@v2)
@import((mirror as m) from fscss:micros)

/* Remote (quotes) */
@import((btn) from "https://cdn.example/buttons.fscss")

/* Local */
@import((card) from "./components/card.fscss")

Libraries: /libraries · modules org: fscss-modules

Console warnings & CSS comments (v1.2.6+)

Duplicate, circular, and failed imports

The compiler logs to the console and often mirrors the same text as a CSS comment in the output so you can spot issues in exported CSS.

Situation Behavior Typical message
Same file imported with * more than once First wins; later skipped /* Can't import <file> multiple times */
Circular graph (a → b → a) Cycle broken; no infinite loop /* Circular import: <file> */
Missing / failed fetch Import skipped /* Failed import: <file> */
Name not exported Error / no binding not defined with @define in module
Call original after as Undefined in this file original name is not defined
* as alias Invalid Cannot assign * to alias
Circular example
/* a.fscss */
@import((*) from "./b.fscss")

/* b.fscss */
@import((*) from "./a.fscss")

/* Output may include: */
/* Circular import: ./a.fscss */
/* Console: FSCSS [@import] … circular / can't import <file> multiple times */
Duplicate * import
@import((*) from "./utils.fscss")
@import((*) from "./utils.fscss")

/* Second becomes a comment, e.g.: */
/* Can't import ./utils.fscss multiple times */
Exact console prefix may look like FSCSS [@import] …. Always check the compiled CSS for the matching /* … */ markers when debugging IDE or CLI output.

Compiler phases (register → extract → substitute)

  1. Registration — @define stores blueprints (no CSS yet).
  2. Extraction — @import binds names / aliases into this file (and resolves the dependency graph in 1.2.6+).
  3. Substitution — calling @name(args) fills @use and emits CSS.

Import stages can still be disabled with exec.obj.block(f import), exec.obj.block(f import pick), or exec.obj.block(f import from) when needed.

Benefits of Using @import

Why Modular Architecture Matters

Using @import provides significant advantages for both development and maintenance.

Organized Code

Split styles into logical files, reduce clutter, and find code faster

Flexible Architecture

Load only what you need, use selective imports, and reuse modules

Team Friendly

Multiple developers can work simultaneously with clear separation

Scalable

Easily add new features without breaking existing code

Performance Note: In development, multiple files are fine. For production, compile with the CLI so the browser receives a single optimized CSS file.

Ready to modularize?

Start with the official modules or build your own. The v1.2.6 runtime resolves chained imports, carries @define dependencies, and surfaces clear circular/duplicate messages.