What Are FSCSS Modules?
An FSCSS module is simply a stylesheet that contains reusable style definitions. Think of them as building blocks for your CSS architecture.
@define radius-util(){`
@arr radius[count(200)]
.radius-@arr.radius[]{
border-radius:@arr.radius[]px;
}
`}
This module defines a reusable utility called radius-util. It doesn't run automatically. Instead, you import it and execute it when you want.
@import((radius-util) from spacing-utils/fscss)
@radius-util()
This generates all the radius utilities from 1px to 200px.
What is @define? Core Concept
The Foundation of Reusable Code
@define creates a reusable block of FSCSS code. Think of it like:
A Function
Takes parameters, returns generated CSS
A Macro
Expands into multiple CSS rules
A Code Generator
Produces CSS on demand
@define card(){`
.card{
padding:20px;
border-radius:10px;
}
`}
/* Then run it: */
@card()
/* Outputs the CSS */
.card{
padding:20px;
border-radius:10px;
}
Why FSCSS Requires @define
FSCSS does not automatically run imported code. This design has several important benefits:
1. Performance
If every import executed immediately, large libraries would generate thousands of unused styles. With @define, nothing runs unless you call it.
@radius-util()
This keeps styles smaller and more efficient.
2. Control
Developers choose exactly which modules to run.
@import((radius-util, margin-util) from spacing-utils/fscss)
@radius-util()
Only radius utilities are generated.
3. Customization
You can overwrite the array used for the specific function
@arr radius[count(100)]
@radius-util()
Which might generate utilities only up to 100.
Named Imports vs Wildcard *
Why Import by Name Instead of *
@import((radius-util) from spacing-utils/fscss)
This imports only that specific definition.
@import((*) from spacing-utils/fscss)
This imports everything from the module.
Disadvantages of *
- All utilities are loaded, even if you don't use them
- Larger compiled CSS output
- Slower compile time
- Potential naming conflicts
Example problem: @import((*) from huge-library) might generate 10,000+ unused classes.
Advantages of Named Imports
@import((radius-util, padding-util) from spacing-utils/fscss)
- Smaller CSS output
- Faster compilation
- Better project organization
- Predictable output
Why FSCSS Libraries Are Usually Remote
@import((icon-base, icon-home) from icon-mask_v2)
/* Resolves to: */
https://cdn.jsdelivr.net/gh/fscss-ttr/FSCSS@main/xf/styles/icon-mask_v2.fscss
FSCSS encourages remote modular libraries because:
1. Sharing
Libraries can be reused across multiple projects without copying files.
2. Updates
When the library improves, users automatically get improvements without manual updates.
3. Distribution
Easy distribution through CDNs and package managers.
What FSCSS Does NOT Allow
Direct Style Imports Without @define
FSCSS does NOT allow:
@import(body from module) ❌ Not allowed
If raw styles were imported directly, it would create several problems:
1. No Control Over Execution
Everything would load automatically, whether you need it or not.
2. Name Collisions
Multiple modules could overwrite each other's styles.
3. Large CSS Output
Unused styles would still be generated, bloating your CSS.
Advantages of @define in Your Own Stylesheet
You can build your own reusable components with parameters:
@define button(color:#6366f1){`
.btn{
background:@use(color);
color:white;
padding:10px 20px;
border-radius:6px;
}
`}
/* Usage with default color */
@button()
/* Usage with custom color */
@button(red)
Building Your Own Modular FSCSS System
Organize Your Modules
You can organize files like this:
fscss-modules/utils.fscss
@define spacing-utils(){/*... */}
@define radius-utils(){/*... */}
@define flex-utils(){/*... */}
@define grid-utils(){/*... */}
@define typography-utils(){/*...*/}
Then import them selectively:
@import((spacing-utils, flex-utils) from "fscss-modules/utils.fscss")
And run them when needed:
@spacing-utils()
@flex-utils()
Module File
Contains @define blocks
Import
Select what you need
Initialize
@module-name()
Is Initializing with @name() Necessary?
Yes, Initialization Is Required
This step executes the defined module. Without it, nothing happens.
@import((radius-util) from spacing-utils/fscss)
If you do not run:
@radius-util()
Then no utilities are generated. The module is imported but not executed.
Why This Design Matters
The FSCSS modular system provides:
| Feature | Benefit |
|---|---|
| Better Control | Choose exactly which styles to generate |
| Smaller CSS Output | Only generate what you actually use |
| Reusable Style Generators | Build once, use everywhere |
| Scalable Architecture | Grows from small projects to large design systems |
FSCSS allows developers to build CSS generators. This makes it possible to create entire utility frameworks using just a few reusable definitions.
Summary
FSCSS modules allow you to treat styles like reusable building blocks. By combining FSCSS methods, developers can create flexible style systems that scale from small projects to large design systems.
Key Takeaway 1
Use @define to create reusable style generators
Key Takeaway 2
Always initialize modules with @name()
Key Takeaway 3
Use named imports instead of * for smaller CSS
The modular approach keeps code organized, reusable, and efficient.