PostCSS plugin for mixins.
Note, that you must set this plugin before postcss-simple-vars and postcss-nested.
@define-mixin icon $network, $color: blue {
.icon.is-$(network) {
color: $color;
@mixin-content;
}
.icon.is-$(network):hover {
color: white;
background: $color;
}
}
@mixin icon twitter {
background: url(twt.png);
}
@mixin icon youtube, red {
background: url(youtube.png);
}
.icon.is-twitter {
color: blue;
background: url(twt.png);
}
.icon.is-twitter:hover {
color: white;
background: blue;
}
.icon.is-youtube {
color: red;
background: url(youtube.png);
}
.icon.is-youtube:hover {
color: white;
background: red;
}
postcss-utilities collection is better for clearfix
and other popular hacks.
For simple cases you can use postcss-define-property.
Step 1: Install plugin:
npm install --save-dev postcss postcss-mixins
Step 2: Check your project for existed PostCSS config: postcss.config.js
in the project root, "postcss"
section in package.json
or postcss
in bundle config.
If you do not use PostCSS, add it according to [official docs] and set this plugin in settings.
Step 3: Add the plugin to plugins list:
module.exports = {
plugins: [
+ require('postcss-mixins'),
require('autoprefixer')
]
}
Simple template defined directly in CSS to prevent repeating yourself.
See postcss-simple-vars docs for arguments syntax.
You can use it with postcss-nested plugin:
@define-mixin icon $name {
padding-left: 16px;
&::after {
content: "";
background: url(/icons/$(name).png);
}
}
.search {
@mixin icon search;
}
Unlike Sass, PostCSS has no if
or while
statements. If you need some
complicated logic, you should use function mixin.
This type of mixin gives you full power of JavaScript.
You can define this mixins in mixins
option.
This type is ideal for CSS hacks or business logic.
Also, you should use function mixin if you need to change property names in mixin, because postcss-simple-vars doesn’t support variables in properties yet.
First argument will be @mixin
node, that called this mixin.
You can insert your declarations or rule before or after this node.
Other arguments will be taken from at-rule parameters.
See PostCSS API about nodes API.
require('postcss-mixins')({
mixins: {
icons: function (mixin, dir) {
fs.readdirSync('/images/' + dir).forEach(function (file) {
var icon = file.replace(/\.svg$/, '');
var rule = postcss.rule({ selector: '.icon.icon-' + icon });
rule.append({
prop: 'background',
value: 'url(' + dir + '/' + file + ')'
});
mixin.replaceWith(rule);
});
}
}
});
@mixin icons signin;
.icon.icon-back { background: url(signin/back.svg) }
.icon.icon-secret { background: url(signin/secret.svg) }
You can also return an object if you don’t want to create each node manually:
require('postcss-mixins')({
mixins: {
image: function (mixin, path, dpi) {
return {
'&': {
background: 'url(' + path + ')'
},
['@media (min-resolution: '+ dpi +'dpi)']: {
'&': {
background: 'url(' + path + '@2x)'
}
}
}
}
}
});
Mixin body will be in mixin.nodes
:
var postcss = require('postcss');
require('postcss-mixins')({
mixins: {
hover: function (mixin) {
let rule = postcss.rule({ selector: '&:hover, &.hover' });
rule.append(mixin.nodes);
mixin.replaceWith(rule);
}
}
});
Or you can use object instead of function:
require('postcss-mixins')({
mixins: {
clearfix: {
'&::after': {
content: '""',
display: 'table',
clear: 'both'
}
}
}
});
@mixin-content
at-rule will be replaced with mixin @mixin
children.
For example, CSS mixins:
@define-mixin isIE {
.isIE & {
@mixin-content;
}
}
or JS mixins:
require('postcss-mixins')({
mixins: {
isIe: function () {
'@mixin-content': {},
}
}
});
could be used like this:
.foo {
color: blue;
@mixin isIE {
color: red;
}
}
// output
.foo { color: blue; }
.isIE .foo { color: red; }
In order to pass a comma-separated value as an argument to a mixin, you can use
the special single-arg
keyword. For example:
@define-mixin transition $properties, $duration {
transition-property: $properties;
transition-duration: $duration;
}
.foo {
@mixin transition single-arg(color, background-color), 0.5s;
}
If you need to use Sass and PostCSS mixins together
(for example, while migration), you could use @add-mixin
,
instead of @mixin
. Just put PostCSS after Sass.
// Legacy SCSS
@mixin old {
…
}
@include old;
// New code
@define-mixin new {
…
}
@add-mixin new;
Call plugin function to set options:
postcss([ require('postcss-mixins')({ mixins: { … } }) ])
Type: Object
Object of function mixins.
Type: string|string[]
Autoload all mixins from one or more dirs. Mixin name will be taken from file name.
// gulpfile.js
require('postcss-mixins')({
mixinsDir: path.join(__dirname, 'mixins')
})
// mixins/clearfix.js
module.exports = {
'&::after': {
content: '""',
display: 'table',
clear: 'both'
}
}
// mixins/size.pcss
@define-mixin size $size {
width: $size;
height: $size;
}
// mixins/circle.sss
@define-mixin circle $size
border-radius: 50%
width: $size
height: $size
Type: string|string[]
Similar to mixinsDir
; except, you can provide
tinyglobby syntax
to target or not target specific files.
require('postcss-mixins')({
mixinsFiles: path.join(__dirname, 'mixins', '!(*.spec.js)')
})
Remove unknown mixins and do not throw a error. Default is false
.