CSS @function At-Rule

The @function at-rule defines reusable custom CSS functions that accept input values and return calculated results. These functions can simplify repeated calculations, organize CSS logic, and generate property values without requiring JavaScript or a CSS preprocessor.

@function Syntax

@function --function-name(--parameter) {
  result: var(--parameter);
}

The at-rule begins with @function, followed by a custom function name, parentheses containing optional parameters, and a declaration block.

Custom function names begin with two hyphens. The result descriptor specifies the value returned when the function is called.

A custom function can be used within a CSS property value by writing its name followed by parentheses.

@function --double(--value) {
  result: calc(var(--value) * 2);
}
.box {
  padding: --double(10px);
}

The function receives 10px, doubles it, and returns 20px for the padding.

How @function Works

Custom CSS functions provide reusable calculations that can return different values depending on their arguments.

When a function is called, the browser evaluates its body using the supplied arguments and substitutes the resulting value into the CSS declaration.

@function --spacing(--amount) {
  result: calc(var(--amount) * 4px);
}
.card {
  padding: --spacing(4);
  margin-bottom: --spacing(6);
}

The first function call returns 16px, while the second returns 24px.

Unlike a CSS custom property, which stores a value, a custom function can accept different arguments each time it is used.

Custom functions are evaluated by the CSS engine and do not require JavaScript.

Function Parameters

Parameters allow a function to receive values when it is called. Each parameter name begins with two hyphens and can be accessed inside the function using var().

Multiple Parameters

@function --add-spacing(--first, --second) {
  result: calc(var(--first) + var(--second));
}
.panel {
  padding: --add-spacing(10px, 5px);
}

The function receives two lengths and returns 15px.

Default Parameter Values

Parameters can include default values that are used when the corresponding argument is omitted.

@function --multiply(--value, --factor: 2) {
  result: calc(var(--value) * var(--factor));
}
.box-one {
  padding: --multiply(10px);
}
.box-two {
  padding: --multiply(10px, 3);
}

The first call returns 20px using the default factor. The second returns 30px using the supplied factor of 3.

Return Values

The result descriptor determines the value returned by a custom function.

@function --brand-color() {
  result: #0056b3;
}
.heading {
  color: --brand-color();
}

This function takes no parameters and returns a fixed color.

A function can also use local custom properties to calculate its result.

@function --triple(--value) {
  --multiplier: 3;
  result: calc(var(--value) * var(--multiplier));
}
.box {
  width: --triple(50px);
}

The local custom property --multiplier is available within the function body. The function returns 150px.

When multiple applicable result descriptors are present, normal CSS source-order and conditional rules determine which value is used. CSS custom functions do not use JavaScript-style early returns.

Data Types

Custom functions can specify the data types accepted by their parameters and returned results.

@function --double-length(--value <length>) returns <length> {
  result: calc(var(--value) * 2);
}
.box {
  padding: --double-length(12px);
}

The <length> type requires a length value, such as 12px or 2rem. The returns keyword specifies that the function must produce a length.

Common supported type definitions include:

Data Type Description
<number> A numeric value without a unit.
<integer> A whole number.
<length> A length value such as pixels or rem units.
<percentage> A percentage value.
<color> A CSS color value.
<angle> An angle value such as degrees.

Type definitions are optional. When no type is specified, a parameter can accept any CSS value. A function result that does not match its declared return type is invalid.

Conditional Logic

Custom functions can include conditional rules to return different values depending on the environment.

Using @media Inside a Function

@function --responsive-spacing() {
  result: 24px;
  @media (max-width: 600px) {
    result: 12px;
  }
}
.container {
  padding: --responsive-spacing();
}

The function returns 24px by default and 12px when the viewport width is 600px or less.

The order matters. The conditional result must appear after the default result so that it can override the default when the condition matches.

Using CSS Conditional Functions

Custom functions can also use the CSS if() function to select between values.

@function --text-spacing() {
  result: if(media(width < 600px): 8px; else: 16px);
}
.text-block {
  margin-bottom: --text-spacing();
}

This example returns 8px for viewports narrower than 600px and 16px otherwise.

Both custom functions and newer conditional functions have browser compatibility limitations that should be checked before production use.

Browser Compatibility

The @function at-rule has limited browser availability and is not yet a Baseline feature across major browsers.

For production websites that require broad compatibility, use standard CSS custom properties, calc(), and media queries where possible.

Standard CSS Alternative

:root {
  --base-spacing: 10px;
}
.box {
  padding: calc(var(--base-spacing) * 2);
}

This alternative calculates 20px of padding without defining a custom function.

Although custom properties cannot accept function arguments, they can provide reusable values for many common calculations.

@function Example

The following example defines a reusable function that calculates spacing values from a numeric multiplier.

@function --space(--units <number>) returns <length> {
  result: calc(var(--units) * 8px);
}
.card {
  padding: --space(2);
  margin-bottom: --space(3);
  border-radius: --space(1);
}

The function uses an 8px spacing unit. It returns 16px for padding, 24px for the bottom margin, and 8px for the border radius.

In browsers without custom function support, these declarations are not a reliable way to apply spacing. Use standard CSS alternatives when compatibility is required.

Browser Support: The @function at-rule has limited availability and is not supported by every major browser. It is an experimental feature. See MDN Web Docs for its browser compatibility table, or visit Can I Use? and search for CSS custom functions.

Specifications

The @function at-rule is defined in the CSS Functions and Mixins Module Level 1 specification. It describes custom function names, parameters, return types, local variables, and conditional evaluation.

CSS Functions and Mixins Module Level 1