Why CSS Custom Functions Matter

For years, CSS developers relied on preprocessors like Sass to bring logic and reusability to stylesheets. But the web platform is catching up. The new CSS @function at-rule (part of the CSS Custom Functions and Mixins Module Level 1) allows you to define native custom functions that accept arguments, perform calculations, and return values — all without any build step.

This is a paradigm shift. Instead of writing repetitive calc() expressions or maintaining Sass libraries, you can now create clean, self-documenting CSS functions that work directly in the browser. Let's explore how.

Source: CSS-Tricks Almanac: @function

CSS custom function syntax and code example on a monitor screen Programming Illustration

Core Syntax & First Example

The @function rule uses a dashed-ident name (like --my-function), optional parameters with type checking, a returns descriptor, and a result descriptor inside the body.

/* Define a function that halves any length value */
@function --half(--size <length>) returns <length> {
  result: calc(var(--size) / 2);
}

/* Use it */
.container {
  margin-inline: --half(20px); /* resolves to 10px */
}

Type Checking

Just like @property, you can enforce argument types:

@function --progression(--current <number>, --total <number>) returns <percentage> {
  result: calc(var(--current) / var(--total) * 100%);
}

.progress-bar {
  width: --progression(3, 5); /* 60% */
}

Comma-Separated Lists

Pass a list as a single argument by wrapping it in curly braces and suffixing # to the parameter:

@function --get-range(--list<length>#, --n <length>) returns <length> {
  result: calc(max(var(--list)) - min(var(--list)) + var(--n));
}

div {
  padding-block: --get-range({10px, 100px, 50px, 25px}, 200px); /* 290px */
}

Conditional Logic with Cascade

The result descriptor respects the cascade. You can use @media, @container, or @supports inside the function:

@function --suitable-font-size() returns <length> {
  result: 16px;
  @media (width > 1000px) {
    result: 20px;
  }
}

body {
  font-size: --suitable-font-size();
}

Nesting Functions & Default Values

@function --square(--n <number>) returns <number> {
  result: calc(var(--n) * var(--n));
}

@function --circle-area(--radius <number>) returns <number> {
  --pi: 3.14159;
  result: calc(var(--pi) * --square(var(--radius)));
}

@function --brand-glass(--opacity: 0.5) returns <color> {
  result: rgb(10 120 255 / var(--opacity));
}

.header {
  background: --brand-glass(); /* 0.5 opacity */
}

Developer writing native CSS @function with type checking on laptop Algorithm Concept Visual

Limitations & Caveats

  • No side effects: @function can only return a value. You cannot change properties or generate multiple declarations inside a function. For that, look to the proposed @mixin at-rule.
  • Circular dependencies: If Function A calls Function B and vice versa, both become invalid. The browser detects this and prevents infinite recursion.
  • Browser support is experimental: Currently only Chrome 148+ supports @function natively. The @supports (at-rule(@function)) check is also not fully supported across browsers yet.
  • Fallback strategy: Always provide fallback declarations for unsupported browsers. For example:
.element {
  width: 60%; /* fallback */
  width: --progression(3, 5);
}

Next Steps

  • Experiment with @function in Chrome Canary or with the chrome://flags/#enable-experimental-web-platform-features flag.
  • Combine with @property for even more type safety and custom property registration.
  • Stay tuned for the @mixin proposal, which will unlock multi-line, stateful CSS logic.

Diagram of CSS cascade and custom functions interaction in web development Technical Structure Concept

Conclusion

CSS @function is a game-changer for maintainable, logic-driven stylesheets. It reduces reliance on preprocessors, improves readability, and brings true programming constructs to CSS — all without JavaScript. While still experimental, it's worth learning now to be ready for the future of web styling.

Related articles:

This content was drafted using AI tools based on reliable sources, and has been reviewed by our editorial team before publication. It is not intended to replace professional advice.