Reusable CSS with Stylus Mixins: Argument‑Driven Local Variables
Learn how to create parameterized, self‑contained CSS blocks in Stylus using mixins that accept arguments and local variables. The article walks through syntax, scoping, a full example, and common pitfalls to avoid.
24 Dec 2025, 18:15 UTC

Why Use Argument‑Enabled Mixins?
In Stylus, a mixin is a reusable block of CSS that you can call with different parameters. By letting mixins accept arguments and declare local variables, you can keep your styles modular, avoid repetition, and maintain a single source of truth for design tokens.
Defining a Parameterized Mixin
Mixins are declared with a trailing block and optional arguments. The syntax is concise: mixinName(arg1, arg2){ … }. Arguments can be positional or keyword‑based.
button(type, color){
background: color
border: 1px solid darken(color, 10%)
padding: .5rem 1rem
border-radius: 4px
&:hover{ background: lighten(color, 10%) }
}
Here, type is unused but kept for semantic clarity, while color drives the visual style.
Local Variables Inside Mixins
Variables prefixed with $ inside a mixin are local; they don’t leak into the global scope. This is crucial to prevent accidental overrides.
button(type, color){
$bg = color
$border = darken($bg, 10%)
background: $bg
border: 1px solid $border
}
When the mixin is invoked, $bg and $border exist only for that call. After compilation, the resulting CSS contains only the final values.
Calling the Mixin With Arguments
To apply the mixin, simply call it like a function. Place the call inside a selector or another mixin.
.btn-primary
button('primary', #ff4d4d)
.btn-secondary
button('secondary', #4d79ff)
Running stylus example.styl -o output.css produces:
.btn-primary{background:#ff4d4d;border:1px solid #e64242;padding:.5rem 1rem;border-radius:4px} .btn-primary:hover{background:#ff7f7f}
.btn-secondary{background:#4d79ff;border:1px solid #4466d6;padding:.5rem 1rem;border-radius:4px} .btn-secondary:hover{background:#7f9bff}
Default Arguments and Optional Parameters
Stylus lets you provide default values so callers can omit arguments. Defaults are defined after the parameter list.
button(type, color = #333){
background: color
}
Calling button() will use #333 as the background color.
Using Mixins as Functions
Mixins can return a value. The last evaluated expression is the return value, enabling dynamic property generation.
calcPadding(base, multiplier){
base * multiplier
}
.box
padding: calcPadding(1rem, 2)
Compiled CSS:
.box{padding:2rem}
Recursive Mixins for Complex Patterns
Because mixins are first‑class, they can call themselves. This is handy for generating nested structures like multi‑column layouts.
columns(count, width){
if count > 0
width: width
columns(count - 1, width)
}
.grid
columns(4, 25%)
The compiled CSS will contain four width:25% declarations, one per recursion level.
Common Pitfalls and Limits
- Implicit globals: Variables without a leading
$become global. Accidentally naming a variablecolorinside a mixin could overwrite a globalcolortoken. - Over‑use for simple property sets: Repeating a mixin that only adds a few properties can bloat the compiled CSS. For lightweight reuse, consider
extendor placeholder selectors. - Large generated CSS: Recursive mixins that produce hundreds of rules (e.g., 100‑column grid) can increase compile time and file size. Test with realistic data sets before deployment.
- Missing default values: If a caller omits an argument that has no default, Stylus will raise a reference error. Always provide defaults for optional parameters.
- Variable scope confusion: Remember that only
$‑prefixed variables stay local. Mixing naming conventions can lead to subtle bugs.
Verifying Your Mixins
After compiling, inspect the CSS to ensure no unexpected variables remain and that defaults work as intended. A quick sanity test: call the mixin without arguments and confirm the fallback values appear.
stylus example.styl -o output.css
# Open output.css and search for the fallback color
Also, run a linter or use Stylus’s --lint flag to catch unused variables or potential scoping issues.
Conclusion
Argument‑enabled mixins with local variables give Stylus developers powerful, modular building blocks. By understanding scoping, defaults, and recursion, you can write clean, maintainable CSS that scales with your design system while avoiding common pitfalls that inflate your compiled styles.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.