Reusable Design Tokens with Stylus Mixins
Use Stylus mixins to centralize spacing, color, and radius values so changing one token updates every component at build time.
30 Jul 2025, 07:51 UTC

The problem: the same declarations everywhere
You copy background-color, padding, and border-radius from one component to the next. When the brand color changes, you run find-and-replace across half a dozen files and still miss one instance. This is exactly the repetition that design tokens are meant to solve, but you do not need runtime CSS variables to start.
Stylus mixins let you define a block of CSS properties once and inject it into any selector. Because Stylus compiles to static CSS, the values are baked in at build time. There is no JavaScript runtime and no browser support question.
Mixins as compile-time design tokens
A mixin is a named group of Stylus properties. You call it inside a selector, and Stylus copies the properties into that selector. A transparent mixin is called without a name, so its properties are injected directly into the current selector instead of generating a separate class. This is useful for utility patterns and shared component styles.
Mixins accept arguments with default values, so one definition can handle several variants. Stylus syntax omits braces and semicolons by default, which keeps definitions compact.
Worked example: a button design system
Create src/styles/buttons.styl:
button-base(padding = 8px 16px, radius = 4px, bg = #2563eb, color = #ffffff)
padding padding
border-radius radius
background-color bg
color color
border none
cursor pointer
font-size 14px
.btn
button-base()
.btn--primary
button-base(bg = #1d4ed8)
.btn--compact
button-base(padding = 4px 10px, radius = 2px)
In this example, button-base() is a transparent mixin call: no class named button-base appears in the output. The properties flow directly into .btn, .btn--primary, and .btn--compact. Changing bg in one place updates every button that uses the default.
Compile from your project terminal:
npx stylus src/styles/buttons.styl -o public/css/buttons.css
Required permissions: read access to the source file and write access to the output directory. No elevated permissions are needed.
Verify the result by opening public/css/buttons.css and checking that .btn contains the inlined properties, not a reference to a mixin. Confirm that .btn--primary uses #1d4ed8 while .btn--compact uses the overridden padding. A quick terminal check:
grep -A 12 "\.btn\b" public/css/buttons.css
Risk: the -o flag overwrites an existing file at the output path without warning. Point it to a new location or back up the file first if you are unsure.
Trade-offs and limitations
- Build-time only. Unlike CSS custom properties, Stylus mixins cannot change after the page loads. If you need theming toggled by JavaScript or user preference, combine mixins with CSS variables or use variables alone.
- Debugging. Deeply nested or heavily argumented mixins can make the compiled CSS harder to map back to the source. Keep mixins small and focused.
- Specificity. Because properties are copied into the selector, they participate in normal CSS specificity. A transparent mixin does not create a wrapper class, so there is no extra specificity layer to manage.
Closing check
Pick one repeated component in your stylesheet, extract its shared declarations into a Stylus mixin, replace the copies with transparent mixin calls, and compile. If the output CSS contains the expected values and no leftover duplication, the pattern is working.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.