postcss-transform-mixins
v0.0.2
Published
PostCSS plugin for transforming CSS mixins to native CSS
Maintainers
Readme
postcss-transform-mixins
A PostCSS plugin for transforming CSS @mixin, @macro, and @apply rules at build time.
This plugin is part of the css-mixin-polyfill project and provides build-time processing of CSS mixin and macro definitions, substituting @apply rules with the corresponding resolved styles — eliminating the need for runtime JavaScript processing.
Input CSS:
@macro --reset-list {
margin: 0;
padding: 0;
list-style: none;
}
.nav {
@apply --reset-list;
}Expected Output:
.nav {
margin: 0;
padding: 0;
list-style: none;
}Installation
npm install postcss-transform-mixins postcssUsage
PostCSS CLI
# Transform CSS using PostCSS CLI
npx postcss input.css --output output.css --use postcss-transform-mixins
# With custom PostCSS config file
npx postcss input.css --output output.css --config postcss.config.jsBasic Programmatic Usage
import postcss from "postcss";
import postcssMixinMacro from "postcss-transform-mixins";
const css = `
@mixin --gradient-text(--from <color>: mediumvioletred, --to <color>: teal) {
@result {
color: var(--from);
}
}
h1 {
@apply --gradient-text(pink, powderblue);
}
`;
const result = await postcss([postcssMixinMacro()]).process(css, {
from: undefined
});
console.log(result.css);Output:
h1 {
color: pink;
}With Options
const result = await postcss([
postcssMixinMacro({
logTransformations: true
})
]).process(css, { from: undefined });With PostCSS Config File
// postcss.config.js (ESM)
import postcssMixinMacro from "postcss-transform-mixins";
export default {
plugins: [
postcssMixinMacro({
logTransformations: process.env.NODE_ENV === "development"
})
]
};// postcss.config.cjs (CommonJS)
module.exports = {
plugins: [require("postcss-transform-mixins")]
};With Popular PostCSS Tools
Vite
// vite.config.js
import { defineConfig } from "vite";
import postcssMixinMacro from "postcss-transform-mixins";
export default defineConfig({
css: {
postcss: {
plugins: [
postcssMixinMacro({
logTransformations: process.env.NODE_ENV === "development"
})
]
}
}
});Webpack
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"postcss-transform-mixins",
{
logTransformations: true
}
]
]
}
}
}
]
}
]
}
};Next.js
// next.config.js
module.exports = {
experimental: {
postcss: {
plugins: {
"postcss-transform-mixins": {
logTransformations: process.env.NODE_ENV === "development"
}
}
}
}
};Options
| Option | Type | Default | Description |
| -------------------- | --------- | ------- | --------------------------------------------------- |
| logTransformations | boolean | false | Whether to log transformation statistics to console |
Supported Transformations
Macros
Macros provide simple, literal substitution of a block of styles at each @apply site.
Input CSS:
@macro --reset-list {
margin: 0;
padding: 0;
list-style: none;
}
.nav {
@apply --reset-list;
}Expected Output:
.nav {
margin: 0;
padding: 0;
list-style: none;
}Mixins
Mixins extend macros with support for parameters, default values, local variables, and @result blocks.
Input CSS:
@mixin --gradient-text(
--from <color>: mediumvioletred,
--to <color>: teal,
--angle: to bottom right
) {
@result {
color: var(--from, var(--to));
@supports (background-clip: text) or (-webkit-background-clip: text) {
background: linear-gradient(var(--angle), var(--from), var(--to));
color: transparent;
-webkit-background-clip: text;
background-clip: text;
}
}
}
h1 {
@apply --gradient-text(pink, powderblue);
}Expected Output:
h1 {
color: var(--from, var(--to));
@supports (background-clip: text) or (-webkit-background-clip: text) {
background: linear-gradient(var(--angle), var(--from), var(--to));
color: transparent;
-webkit-background-clip: text;
background-clip: text;
}
}Macros with @contents
Macros (and mixins) can accept a contents block via @contents, allowing callers to inject styles into a predefined structure.
Input CSS:
@macro --one-column {
@media (width <= 800px) {
@contents;
}
}
body {
@apply --one-column {
display: flex;
flex-flow: column;
}
}Expected Output:
body {
@media (width <= 800px) {
display: flex;
flex-flow: column;
}
}Limitations
- Static Analysis Only: The plugin performs static analysis at build time and cannot handle dynamically generated CSS or runtime-dependent values
- PostCSS Compatibility: Requires PostCSS 8.0.0 or higher
Integration with Runtime Polyfill
For complete CSS @mixin/@macro/@apply support — including runtime evaluation, hygienic variable renaming, and dynamic argument resolution — combine this plugin with the runtime polyfill:
- Use this PostCSS plugin for build-time transformation of
@mixin,@macro, and@applyrules - Use css-mixin-polyfill runtime for full browser-side support
<!-- For full runtime mixin/macro support -->
<script src="https://cdn.jsdelivr.net/npm/css-mixin-polyfill/dist/index.modern.js"></script>Performance Considerations
This plugin is designed for optimal build-time performance, transforming CSS @mixin and @macro definitions and resolving @apply rules into native CSS without runtime overhead.
For most typical usage scenarios, the performance is excellent and the overhead is negligible compared to the benefits of build-time transformation.
Contributing
See the main Contributing Guide for details on how to contribute to this project.
License
MIT © Maximilian Franzke
Related
- PostCSS - Tool for transforming CSS with JavaScript
- CSS Mixins & Functions - CSS specification for
@mixin,@macro, and@apply
Further solutions
- css-mixin-polyfill - Runtime polyfill for CSS mixins
- stylelint-config-mixin - Stylelint configuration for linting CSS mixin usage
