Skip to main content

Types for Variables

Note

The unstable_moduleResolution option needs to be enabled in the StyleX Babel configuration to enable theming APIs.

Advanced use-cases

Declaring types for variables is an advanced use-case. It is not necessary for the majority of use-cases.

By default, variables values are strings. This is the correct choice for the majority of use-cases. However, modern browsers support defining types for CSS variables. A variable can be declared with an @property rule that specifies the <syntax> type of the variable.

Doing so can enable some interesting use-cases that would otherwise not be possible with CSS. Some examples include:

  • Animating gradients by animating an angle or color variables
  • Capturing the value of 1em on an element and using it on a descendant
  • Converting a floating point number to an integer

API

To assign types to variables in StyleX, you can use the various functions, such as stylex.types.color or stylex.types.length.

Reference the API documentation for a full list of available functions.

Usage

To assign types to variables, the value of the variable can be wrapped in with the appropriate type function.

For example, consider the following set of variables:

tokens.stylex.js
import * as stylex from '@stylexjs/stylex';

export const tokens = stylex.defineVars({
primaryText: 'black',
secondaryText: '#333',
borderRadius: '4px',
angle: '0deg',
int: '2',
});

Currently, all the values can be arbitrary strings. To assign types to the variables, they can be wrapped with the appropriate type function:

tokens.stylex.js
import * as stylex from '@stylexjs/stylex';

export const tokens = stylex.defineVars({
primaryText: stylex.types.color('black'),
secondaryText: stylex.types.color('#333'),
borderRadius: stylex.types.length('4px'),
angle: stylex.types.angle('0deg'),
int: stylex.types.integer(2),
});

Conditional Values

The usage remains unchanged even when at-rules are used within the values. The following is completely valid:

tokens.stylex.js
import * as stylex from '@stylexjs/stylex';

export const colors = stylex.defineVars({
primaryText: stylex.types.color({default: 'black', [DARK]: 'white'}),
});

Type-safety in your source code

The primary utility of stylex.types.* functions is to enable functionality by declaring types for variables in the generated CSS. However, the StyleX API also enhances the type-safety within your own codebase.

When a variable is declared with a certain type within stylex.defineVars, the static types will enforce that the same type function is used when the variable is themed within a stylex.createTheme call.

theme.js
import * as stylex from '@stylexjs/stylex';
import {tokens} from './tokens.stylex.js';

export const highContrast = stylex.createTheme(tokens, {
primaryText: stylex.types.color('black'),
secondaryText: stylex.types.color('#222'),
borderRadius: stylex.types.length('8px'),
angle: stylex.types.angle('0deg'),
int: stylex.types.integer(4),
});

Since the types for the variables are already declared within the stylex.defineVars call, the usage type functions within stylex.createTheme is functionally a no-op, but is required by the static types for type-safety.

Example use-cases

Simulating round()

Modern browsers are starting to support the round() function in CSS. However, the feature can be simulated with a variable with an integer type:

const styles = stylex.create({
gradient: {
// Math.floor
[tokens.int]: `calc(16 / 9)`

// Math.round
[tokens.int]: `calc((16 / 9) + 0.5)`
},
})

Since tokens.int is declared with an integer type, any fractional value is discarded and the value is cast into an integer type whenever a value is assigned.

Animating gradients

It is usually not possible to animate gradients. However, by using a typed angle variable, the gradient can be animated by animating the angle used within it.

Instead of animating a normal CSS property, the angle variable can be animated with stylex.keyframes:

import * as stylex from '@stylexjs/stylex';
import {tokens} from './tokens.stylex';

const rotate = stylex.keyframes({
from: { [tokens.angle]: '0deg' },
to: { [tokens.angle]: '360deg' },
});

const styles = stylex.create({
gradient: {
backgroundImage: `conic-gradient(from ${tokens.angle}, ...colors)`,
animationName: rotate,
animationDuration: '10s',
animationTimingFunction: 'linear',
animationIterationCount: 'infinite',
},
})

This can be used to create rotating conic gradients: