PostCSS Custom Functions 
npm install @csstools/postcss-custom-functions --save-dev
PostCSS Custom Functions lets you use @function custom functions following CSS Custom Functions and Mixins 1.
Custom functions are still an early draft.
This plugin is only a partial implementation to avoid conflicts with the final specification.
Unsupported:
- typed parameters without default values
- return types other than the default
type(*) @functiondefinitions inside@containeror@scope@functiondefinitions inside a@layerthat is itself inside a conditional group rule@functiondefinitions inside a style rule- definitions whose body contains anything other than declarations and conditional group rules
resultdescriptors that resolve to a CSS-wide keyword through a conditional rule or avar()fallback- validation that a typed default value matches its parameter type
Definitions inside @layer, @media and @supports are supported. When a name
has several active definitions, the browser cascade selects the strongest one.
Unsupported definitions are left as-is. A definition is only removed when every
call site is transformed by this plugin, so call sites that are left as-is (for
example inside @keyframes or a nested conditional declaration) keep their
definitions.
Untyped parameters with default values are supported and may use any value,
including relative units and var() references.
Typed parameters with default values are checked by the browser through a
generated @property registration. A default value that is not
computationally independent (for example 1em or var(--x)) can not be used
as an initial-value and makes the function unsupported.
@function --negative(--value) {
result: calc(-1 * var(--value));
}
@function --double(--value <length>: 1px) {
result: calc(2 * var(--value));
}
html {
--gap: 1em;
padding: --negative(var(--gap));
margin: --double(4px);
}
/* becomes */
html {
--gap: 1em;
--_csstools-cf-1gice1e-1-arg-0: var(--gap);
--_csstools-cf-1gice1e-0-result: calc(-1 * var(--_csstools-cf-1gice1e-1-arg-0));
padding: var(--_csstools-cf-1gice1e-0-result);
--_csstools-cf-1gice1e-3-arg-0: 4px;
--_csstools-cf-1gice1e-2-result: calc(2 * var(--_csstools-cf-1gice1e-3-arg-0));
margin: var(--_csstools-cf-1gice1e-2-result);
}
@property --_csstools-cf-1gice1e-3-arg-0 {
syntax: "<length>";
inherits: false;
initial-value: 1px;
}
Usage
Add PostCSS Custom Functions to your project:
npm install postcss @csstools/postcss-custom-functions --save-dev
Use it as a PostCSS plugin:
const postcss = require('postcss');
const postcssCustomFunctions = require('@csstools/postcss-custom-functions');
postcss([
postcssCustomFunctions(/* pluginOptions */)
]).process(YOUR_CSS /*, processOptions */);
Options
preserve
The preserve option determines whether the original notation
is preserved. By default, it is not preserved.
postcssCustomFunctions({ preserve: true })
@function --negative(--value) {
result: calc(-1 * var(--value));
}
@function --double(--value <length>: 1px) {
result: calc(2 * var(--value));
}
html {
--gap: 1em;
padding: --negative(var(--gap));
margin: --double(4px);
}
/* becomes */
@function --negative(--value) {
result: calc(-1 * var(--value));
}
@function --double(--value <length>: 1px) {
result: calc(2 * var(--value));
}
html {
--gap: 1em;
--_csstools-cf-1gice1e-1-arg-0: var(--gap);
--_csstools-cf-1gice1e-0-result: calc(-1 * var(--_csstools-cf-1gice1e-1-arg-0));
padding: var(--_csstools-cf-1gice1e-0-result);
padding: --negative(var(--gap));
--_csstools-cf-1gice1e-3-arg-0: 4px;
--_csstools-cf-1gice1e-2-result: calc(2 * var(--_csstools-cf-1gice1e-3-arg-0));
margin: var(--_csstools-cf-1gice1e-2-result);
margin: --double(4px);
}
@property --_csstools-cf-1gice1e-3-arg-0 {
syntax: "<length>";
inherits: false;
initial-value: 1px;
}