Utilities
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:
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;
:root {
--spacing: 1rem;
--spacing--sm: 0.75rem;
--spacing--md: var(--spacing);
--spacing--lg: 1.25rem;
}
._margin {
margin: var(--spacing);
}
._margin\:sm {
margin: var(--spacing--sm);
}
._margin\:md {
margin: var(--spacing--md);
}
._margin\:lg {
margin: var(--spacing--lg);
}
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.
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.
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:
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;
:root {
--color--primary: #007bff;
--color--secondary: #6c757d;
}
._background\:primary {
background: var(--color--primary);
}
._background\:secondary {
background: var(--color--secondary);
}
._background\:red {
background: red;
}
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:
- 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. - Ref objects (
ref(variable)): Direct references to variable instances - Arbitrary values (
"value"): Plain string values
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;
:root {
--color--primary: #007bff;
--color--secondary: #6c757d;
--color--success: #28a745;
}
._background\:color\.primary {
background: var(--color--primary);
}
._background\:color\.secondary {
background: var(--color--secondary);
}
._background\:\[red\] {
background: red;
}
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.
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;
:root {
--color--primary: #007bff;
--color--secondary: #6c757d;
}
._background\:primary {
background: var(--color--primary);
}
._background\:secondary {
background: var(--color--secondary);
}
._background\:\[red\] {
background: red;
}
Using Utility Modifiers
Both object and array syntax support an optional second parameter for utility modifiers, allowing you to create responsive or stateful variations:
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;
:root {
--color--primary: #007bff;
--color--secondary: #6c757d;
}
._background\:color\.primary {
background: var(--color--primary);
}
._background\:color\.secondary {
background: var(--color--secondary);
}
._hover\:background\:color\.primary {
&:hover {
background: var(--color--primary);
}
}
._hover\:background\:color\.secondary {
&:hover {
background: var(--color--secondary);
}
}
color.primary) and wraps arbitrary values in brackets (e.g., [red]). Use a custom autogenerate function to create shorter or more semantic class names.Examples
Layout Utilities
Build flexible layout systems with display and positioning utilities:
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;
._display\:block {
display: block;
}
._display\:inline-block {
display: inline-block;
}
._display\:inline {
display: inline;
}
._display\:flex {
display: flex;
}
._display\:inline-flex {
display: inline-flex;
}
._display\:grid {
display: grid;
}
._display\:none {
display: none;
}
._flex-direction\:row {
flex-direction: row;
}
._flex-direction\:column {
flex-direction: column;
}
._justify-content\:start {
justify-content: flex-start;
}
._justify-content\:center {
justify-content: center;
}
._justify-content\:end {
justify-content: flex-end;
}
._justify-content\:between {
justify-content: space-between;
}
._align-items\:start {
align-items: flex-start;
}
._align-items\:center {
align-items: center;
}
._align-items\:end {
align-items: flex-end;
}
._align-items\:stretch {
align-items: stretch;
}
Complex Utilities
Create sophisticated utility systems that handle complex CSS properties and calculations:
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;
._grid-column\:1 {
grid-column: span 1 / span 1;
}
._grid-column\:2 {
grid-column: span 2 / span 2;
}
._grid-column\:3 {
grid-column: span 3 / span 3;
}
/* ... */
._grid-column\:12 {
grid-column: span 12 / span 12;
}
Best Practices
- Keep utilities focused: Each utility should have a single, clear responsibility and do one thing well.
- Use descriptive naming: The
_property:valueformat 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.pathreferences to reduce boilerplate. - Customize auto-generate for cleaner class names: Provide a custom
autogeneratefunction 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
_property:value format is more natural and CSS-like, making it intuitive for developers familiar with CSS. It clearly separates the property from the value while maintaining readability._property:value format naturally prevents most conflicts by being explicit about the CSS property being targeted. Modifiers further namespace utilities by prefixing them with the modifier name.autogenerate function in your styleframe options. This function receives the utility name and value, allowing you to return a custom key string. For example, you can extract just the last segment of a token path (@color.primary → primary) instead of using the full path.Interpolation
Styleframe interpolation provides a powerful CSS template literal utility that enables dynamic value insertion with full type safety. Create flexible, maintainable CSS values that adapt to your design system.
Utility Modifiers
Styleframe utility modifiers transform utility declarations to create conditional variations like hover states, media queries, and breakpoints. Build composable utility variants with full type safety.