API Essentials

Utilities

Styleframe utilities provide reusable, single-purpose CSS classes with full type safety and recipe support. Build consistent, maintainable styling systems with atomic design patterns.

Overview

Utilities in Styleframe are reusable, single-purpose CSS classes that provide a foundation for atomic design patterns. They offer full type safety, auto-complete, and seamless integration with recipes to create flexible, maintainable styling systems that scale with your project.

Why use utilities?

Utilities help you:

  • Build atomic design patterns: Create small, focused CSS classes that do one thing well and can be composed together.
  • Maintain consistency: Ensure uniform spacing, colors, and typography across your entire application.
  • Enable rapid prototyping: Quickly build interfaces by combining pre-defined utility classes.
  • Integrate with recipes: Seamlessly work with responsive, state, and custom variants for maximum flexibility.

Defining Utilities

You define utilities using the utility() function from your styleframe instance:

styleframe.config.ts
import { styleframe } from "styleframe";

const s = styleframe();
const { variable, ref, utility } = s;

const spacing = variable("spacing", "1rem");
const spacingSm = variable("spacing.sm", "0.75rem");
const spacingMd = variable("spacing.md", ref(spacing));
const spacingLg = variable("spacing.lg", "1.25rem");

const createMarginUtility = utility("margin", ({ value }) => ({
    margin: value,
}));

createMarginUtility({
    default: ref(spacing),
    sm: ref(spacingSm),
    md: ref(spacingMd),
    lg: ref(spacingLg),
});

export default s;

The utility() function takes a base name and a factory function. The base name is used to generate the utility class names, while the factory function defines how the utility should be applied.

The factory function receives a context object that includes:

  • value: The current value being processed from the entries object
  • Other declaration context helpers such as selector, variable, ref, media, etc.

The function returns a utility creator that you can call with an object containing value mappings (required), and an optional array of utility modifiers.

Good to know: You can write utility names using kebab-case, camelCase, or PascalCase. When generating the utility classes, Styleframe will automatically convert them to kebab-case for consistency.

The default generated utility class format is _property-name:value, which is intuitive and CSS-like. You can customize this format in your styleframe configuration if needed.

Pro tip: Use descriptive utility names that clearly indicate their purpose. The CSS-like syntax makes utilities intuitive and easy to understand.

Using Utility Creators

Once you've defined a utility with the utility() function, you receive a utility creator function. This creator can be called in two ways:

  • With an object containing explicit key-value pairs
  • With an array of values for auto-generated keys

Object Syntax (Explicit Keys)

The object syntax gives you full control over utility class names. Each key in the object corresponds to a utility class name suffix, and the value is passed to the factory function:

styleframe.config.ts
import { styleframe } from "styleframe";

const s = styleframe();
const { variable, ref, utility } = s;

const colorPrimary = variable("color.primary", "#007bff");
const colorSecondary = variable("color.secondary", "#6c757d");

const createBackgroundUtility = utility("background", ({ value }) => ({
    background: value,
}));

// Using object syntax with explicit key-value pairs
createBackgroundUtility({
    primary: ref(colorPrimary),     // => _background:primary
    secondary: ref(colorSecondary), // => _background:secondary
    red: "red",                     // => _background:red
});

export default s;

Array Syntax (Auto-generated Keys)

Instead of manually defining key-value pairs, you can pass an array of values to automatically generate utility class names. This is particularly useful when working with design tokens or when you want to quickly create utilities from a set of values.

When using an array, Styleframe supports three types of values:

  1. Token references (@token.path): References to design tokens using the @ prefix. The referenced variable must exist at the root level — an error is thrown at compile time if it doesn't.
  2. Ref objects (ref(variable)): Direct references to variable instances
  3. Arbitrary values ("value"): Plain string values
styleframe.config.ts
import { styleframe } from "styleframe";

const s = styleframe();
const { variable, ref, utility } = s;

const colorPrimary = variable("color.primary", "#007bff");
const colorSecondary = variable("color.secondary", "#6c757d");
const colorSuccess = variable("color.success", "#28a745");

const createBackgroundUtility = utility("background", ({ value }) => ({
    background: value,
}));

// Using an array with different value types
createBackgroundUtility([
    ref(colorPrimary),      // Ref object => _background:color.primary
    "@color.secondary",     // Token reference => _background:color.secondary
    "red",                  // Arbitrary value => _background:[red]
]);

export default s;

Custom Auto-generate Function

You can customize how utility class names are generated from values by providing an autogenerate function in your styleframe options. This function receives the utility name and value, and returns a custom key string.

styleframe.config.ts
import { styleframe, transformUtilityKey } from "styleframe";

const s = styleframe();
const { variable, ref, utility } = s;

const colorPrimary = variable("color.primary", "#007bff");
const colorSecondary = variable("color.secondary", "#6c757d");

const createBackgroundUtility = utility("background", ({ value }) => ({
    background: value,
}), {
    autogenerate: transformUtilityKey((key) => key.replace('color.', ''))
});

// With custom autogenerate, keys are simplified
createBackgroundUtility([
    ref(colorPrimary),      // => _background:primary
    "@color.secondary",     // => _background:secondary
    "red",                  // => _background:[red]
]);

export default s;

Using Utility Modifiers

Both object and array syntax support an optional second parameter for utility modifiers, allowing you to create responsive or stateful variations:

styleframe.config.ts
import { styleframe } from "styleframe";

const s = styleframe();
const { variable, ref, utility, modifier } = s;

const colorPrimary = variable("color.primary", "#007bff");
const colorSecondary = variable("color.secondary", "#6c757d");

const hover = modifier("hover", ({ declarations }) => ({
    [`&:hover`]: declarations,
}));

const createBackgroundUtility = utility("background", ({ value }) => ({
    background: value,
}));

// Works with both object and array syntax
createBackgroundUtility(
    [
        ref(colorPrimary),
        "@color.secondary",
    ],
    [hover],
);

export default s;
Good to know: The default auto-generate behavior creates keys based on the full token path for references (e.g., color.primary) and wraps arbitrary values in brackets (e.g., [red]). Use a custom autogenerate function to create shorter or more semantic class names.
Pro tip: The examples above show how to pass modifiers to utility creators. To learn how to define your own modifiers, see the Utility Modifiers API documentation →.

Examples

Layout Utilities

Build flexible layout systems with display and positioning utilities:

styleframe.config.ts
import { styleframe } from "styleframe";

const s = styleframe();
const { utility } = s;

const createDisplayUtility = utility("display", ({ value }) => ({
    display: value,
}));

createDisplayUtility({
    block: "block",
    "inline-block": "inline-block",
    inline: "inline",
    flex: "flex",
    "inline-flex": "inline-flex",
    grid: "grid",
    none: "none",
});

const createFlexDirectionUtility = utility("flex-direction", ({ value }) => ({
    flexDirection: value,
}));

createFlexDirectionUtility({
    row: "row",
    column: "column",
});

const createJustifyContentUtility = utility("justify-content", ({ value }) => ({
    justifyContent: value,
}));

createJustifyContentUtility({
    start: "flex-start",
    center: "center",
    end: "flex-end",
    between: "space-between",
});

const createAlignItemsUtility = utility("align-items", ({ value }) => ({
    alignItems: value,
}));

createAlignItemsUtility({
    start: "flex-start",
    center: "center",
    end: "flex-end",
    stretch: "stretch",
});

export default s;

Complex Utilities

Create sophisticated utility systems that handle complex CSS properties and calculations:

styleframe.config.ts
import { styleframe } from "styleframe";

const s = styleframe();
const { variable, ref, utility, css } = s;

const createGridColumnUtility = utility("grid-column", ({ value }) => ({
    gridColumn: css`span ${value} / span ${value}`,
}));

const gridSpanMap = {};
for (let i = 1; i <= 12; i++) {
    gridSpanMap[i] = i;
}

createGridColumnUtility(gridSpanMap);

export default s;

Best Practices

  • Keep utilities focused: Each utility should have a single, clear responsibility and do one thing well.
  • Use descriptive naming: The _property:value format makes utilities intuitive and CSS-like to use.
  • Leverage variables: Build utilities on top of your design system variables for consistency and maintainability.
  • Create composables: Group related utilities into composable functions for better organization and reusability.
  • Integrate with variants: Design utilities to work seamlessly with responsive, state, and custom variants.
  • Batch utility creation: Use object mapping to create multiple related utilities efficiently.
  • Use auto-generation for token-based utilities: When your utilities map directly to design tokens, use arrays with @token.path references to reduce boilerplate.
  • Customize auto-generate for cleaner class names: Provide a custom autogenerate function to create shorter, more semantic utility class names from token paths.
  • Leverage modifiers for conditional variants: Pass modifiers to utility creators for hover, focus, responsive, and other conditional styles.

FAQ