Introduction to FSCSS @define

RECOMMENDED

The @define method in FSCSS allows you to create reusable style definitions that can accept parameters. Think of them as lightweight, parameterized mixins that generate CSS directly at compile time.

Unlike traditional CSS preprocessor mixins, FSCSS defines operate as direct string generators, injecting final CSS output during compilation. This makes them predictable, performant, and perfect for building component systems.

Reusable

Define once, use anywhere across your project

Parameter Support

Accept inputs with configurable default values

Two Modes

Property defines and block defines for any use case

Direct Output

Expands to final CSS during compilation

Key Concept: Parameters must be accessed using @use() inside define bodies. This ensures the compiler correctly resolves parameter values.

Basic Syntax

Define Declaration

@define

The basic syntax for creating a define:

syntax.fscss
@define name(param: default) {
  property: @use(param);
  /* more properties */
}

Simple Define

example.fscss
@define center() {
  display: flex;
  justify-content: center;
  align-items: center;
}

.box {
  @center()
}

Parameters and @use()

Working with Parameters

@use()

Defines can accept parameters with optional default values. Parameters must be accessed using @use().

⚠️ Important: Always use @use(parameter) to access parameter values. Direct references like background: bg; will not work.

✅ Correct Usage

@define card(bg: black, color: white) {
  background: @use(bg);
  color: @use(color);
}

❌ Incorrect Usage

@define card(bg: black, color: white) {
  background: bg;    /* Won't work */
  color: color;      /* Won't work */
}
parameter-example.fscss
@define card(bg: black, color: white, pad: 20px, bd-r: 10px) {
  background: @use(bg);
  border-radius: @use(bd-r);
  padding: @use(pad);
  color: @use(color);
}

.box {
  @card(#007999)
}
Card with parameterized styles

Property Defines vs Block Defines

Property Defines

Property

Generate reusable groups of CSS properties. Ideal for layout utilities, flex/grid helpers, and common styling patterns.

@define flexCenter() {
  display: flex;
  justify-content: center;
  align-items: center;
}

@define roundedCorners(radius: 8px) {
  border-radius: @use(radius);
  overflow: hidden;
}

.container {
  @flexCenter()
  @roundedCorners(12px)
}

Block Defines

Block

Generate full CSS structures like media queries or nested rules. They use string blocks enclosed in quotes.

@define mobile(size) {
  "
  @media (max-width: @use(size)) {
    .container {
      padding: 10px;
    }
    .box {
      width: 100%;
    }
  }
  "
}

@mobile(768px)

Practical Examples

Building a Component System

Components

Create a complete button component system using defines:

buttons.fscss
/* Base button define */
@define btn-base(pad: 0.75rem 1.5rem, fs: 1rem, weight: 600) {
  padding: @use(pad);
  font-size: @use(fs);
  font-weight: @use(weight);
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.3s ease;
  display: inline-block;
  text-align: center;
}

/* Variant defines */
@define btn-primary(bg: #3b82f6, color: white) {
  background: @use(bg);
  color: @use(color);
  
  &:hover {
    background: darken(@use(bg), 10%);
  }
}

@define btn-outline(color: #3b82f6) {
  background: transparent;
  color: @use(color);
  border: 2px solid @use(color);
  
  &:hover {
    background: @use(color);
    color: white;
  }
}

/* Usage */
.primary-btn {
  @btn-base()
  @btn-primary()
}

.outline-btn {
  @btn-base(pad: 0.75rem 2rem)
  @btn-outline(#7c3aed)
}

Responsive System with Block Defines

Responsive

Create a responsive helper system using block defines:

responsive.fscss
/* Responsive breakpoint defines */
@define respond-to(breakpoint) {
  "
  @media (min-width: @use(breakpoint)) {
    /* styling... */ 
  }
  "
}

@define mobile-only() {
  "
  @media (max-width: 767px) {
    /* styling... */
  }
  "
}

@define dark-mode() {
  "
  @media (prefers-color-scheme: dark) {
    /* styling... */
  }
  "
}

Composing Multiple Defines

Combine Defines for Complex Components

Multiple defines can be combined within a single rule for powerful composition:

card-component.fscss
@define card-base(pad: 1.5rem) {
  padding: @use(pad);
  background: white;
  border-radius: 12px;
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}

@define card-header() {
  border-bottom: 1px solid #eaeaea;
  margin-bottom: 1rem;
  padding-bottom: 0.75rem;
}

@define card-footer() {
  border-top: 1px solid #eaeaea;
  margin-top: 1rem;
  padding-top: 0.75rem;
}

@define flexCenter() {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Compose them together */
.product-card {
  @card-base()
  
  .card-title {
    font-size: 1.5rem;
    font-weight: 600;
    @card-header()
  }
  
  .card-content {
    @flexCenter()
    min-height: 200px;
  }
  
  .card-actions {
    @card-footer()
    @flexCenter()
    gap: 1rem;
  }
}

Importing Define Libraries

Share Defines Across Projects

@import

Defines can be organized into libraries and shared through external files:

_theme.fscss

/* Theme defines */
@define light-theme() {
  --bg: #ffffff;
  --text: #333333;
  --primary: #3b82f6;
}

@define dark-theme() {
  --bg: #1a1a1a;
  --text: #f0f0f0;
  --primary: #60a5fa;
}

_layout.fscss

/* Layout defines */
@define container(max: 1200px) {
  max-width: @use(max);
  margin: 0 auto;
  padding: 0 1rem;
}

@define grid(cols: 3, gap: 2rem) {
  display: grid;
  grid-template-columns: repeat(@use(cols), 1fr);
  gap: @use(gap);
}
main.fscss
/* Import define libraries */
@import(exec(_theme.fscss))
@import(exec(_layout.fscss))

/* Use the defines */

:root{
  @light-theme()
} 
:root.dark-theme{
  @dark-theme()
} 

body {
  background: var(--bg);
  color: var(--text);
}

.container {
  @container()
}

.product-grid {
  @grid(4, 1.5rem)
}

Best Practices

Use Property Defines for Utilities

Keep property defines focused on single responsibilities like flex center, rounded corners, or shadows

Use Block Defines for Complex Structures

Reserve block defines for media queries, keyframes, and nested rule structures

Provide Default Values

Always include sensible defaults for parameters to make defines flexible yet usable out of the box

Keep Defines Focused

Each define should do one thing well. Compose multiple defines for complex components

Pro Tip: Organize your defines into logical files (e.g., _buttons.fscss, _layout.fscss, _animations.fscss) and import them as needed. This creates a maintainable component library.

Why Use FSCSS Defines?

Benefits of Reusable Definitions

Reduce Repetition

Write styles once, use them everywhere. Eliminate duplicate code across your project

Maintain Consistency

Changes to a define update everywhere it's used, ensuring design consistency

Build Component Systems

Create a library of reusable components that can be composed together

Faster Development

Build new UI elements quickly by combining existing defines

Feature Benefit
Reusable styles Reduce repetition and maintenance overhead
Parameter support Flexible components that adapt to different contexts
Direct expansion Predictable output with no runtime overhead
Plugin-friendly Share define libraries across projects and teams