Sass Mixin
Mixins let you package up reusable groups of CSS declarations, complete with optional arguments, so you never have to retype the same rules across selectors.
Defining a Mixin
A mixin is declared with the @mixin keyword followed by a name and a block of styles. Anything you could write inside a normal selector can go inside a mixin, including properties, nested selectors, and even media queries. On its own, a mixin produces no CSS; it only becomes useful once you include it somewhere.
A simple mixin
<!DOCTYPE html>
<html>
<head>
<style id="compiled-css"></style>
</head>
<body>
<section class="hero">Hero section</section>
<script src="https://cdn.jsdelivr.net/npm/sass.js@0.11.1/dist/sass.sync.js"></script>
<script>
Sass.setWorkerUrl('https://cdn.jsdelivr.net/npm/sass.js@0.11.1/dist/sass.worker.js');
var sass = new Sass();
var scss = "@mixin flex-center {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.hero {\n @include flex-center;\n min-height: 40vh;\n}";
sass.compile(scss, function (result) {
if (result && typeof result.text === "string") {
document.getElementById("compiled-css").textContent = result.text;
} else {
var msg = (result && (result.formatted || result.message)) || "Unknown Sass compile error";
var pre = document.createElement("pre");
pre.style.color = "#b00020";
pre.style.whiteSpace = "pre-wrap";
pre.style.fontFamily = "monospace";
pre.style.padding = "16px";
pre.textContent = "Sass compile error:\n" + msg;
document.body.prepend(pre);
}
});
</script>
</body>
</html>Pulling a Mixin Into a Selector With @include
The @include rule is what actually inserts a mixin's styles into a selector. You can @include the same mixin in as many selectors as you like, and each one gets its own independent copy of the compiled CSS.
- @mixin defines a reusable block of styles once.
- @include inserts that block wherever it's needed.
- Mixins can accept arguments to customize the output per call.
- Mixins can contain nested rules, not just flat properties.
- Unlike functions, mixins return styles, not a single value.
Mixins With Arguments
Arguments make mixins genuinely powerful. You declare parameters in parentheses after the mixin name, and callers pass values when they @include it, similar to calling a function in any programming language.
A mixin with required and default arguments
<!DOCTYPE html>
<html>
<head>
<style id="compiled-css"></style>
</head>
<body>
<button class="btn-primary">Primary</button>
<button class="btn-danger">Danger</button>
<script src="https://cdn.jsdelivr.net/npm/sass.js@0.11.1/dist/sass.sync.js"></script>
<script>
Sass.setWorkerUrl('https://cdn.jsdelivr.net/npm/sass.js@0.11.1/dist/sass.worker.js');
var sass = new Sass();
var scss = "@mixin button($bg, $color: white, $radius: 4px) {\n background-color: $bg;\n color: $color;\n border-radius: $radius;\n padding: 0.5em 1.25em;\n border: none;\n}\n\n.btn-primary {\n @include button(#2b6cb0);\n}\n\n.btn-danger {\n @include button(#c53030, $radius: 2px);\n}";
sass.compile(scss, function (result) {
if (result && typeof result.text === "string") {
document.getElementById("compiled-css").textContent = result.text;
} else {
var msg = (result && (result.formatted || result.message)) || "Unknown Sass compile error";
var pre = document.createElement("pre");
pre.style.color = "#b00020";
pre.style.whiteSpace = "pre-wrap";
pre.style.fontFamily = "monospace";
pre.style.padding = "16px";
pre.textContent = "Sass compile error:\n" + msg;
document.body.prepend(pre);
}
});
</script>
</body>
</html>In the example above, $color and $radius have default values, so callers only need to supply them when they want something different from the default. The second call also shows named arguments, where you specify the parameter name directly, letting you skip earlier optional arguments cleanly.
Variable Argument Lists
When a mixin needs to accept an unknown number of values, such as a list of box-shadow layers, you can use the ... syntax to capture the rest of the arguments into a single list.
Accepting any number of arguments
<!DOCTYPE html>
<html>
<head>
<style id="compiled-css"></style>
</head>
<body>
<div class="card">Card with layered shadows</div>
<script src="https://cdn.jsdelivr.net/npm/sass.js@0.11.1/dist/sass.sync.js"></script>
<script>
Sass.setWorkerUrl('https://cdn.jsdelivr.net/npm/sass.js@0.11.1/dist/sass.worker.js');
var sass = new Sass();
var scss = "@mixin shadows($shadows...) {\n box-shadow: $shadows;\n}\n\n.card {\n @include shadows(0 1px 2px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08));\n}";
sass.compile(scss, function (result) {
if (result && typeof result.text === "string") {
document.getElementById("compiled-css").textContent = result.text;
} else {
var msg = (result && (result.formatted || result.message)) || "Unknown Sass compile error";
var pre = document.createElement("pre");
pre.style.color = "#b00020";
pre.style.whiteSpace = "pre-wrap";
pre.style.fontFamily = "monospace";
pre.style.padding = "16px";
pre.textContent = "Sass compile error:\n" + msg;
document.body.prepend(pre);
}
});
</script>
</body>
</html>Exercise: Sass Mixin
How do you define a reusable, parameterized block of styles in Sass?