Mixins vs @extend: Which Minimizes Generated CSS Size in Stylus?
0 reputation · 15 May 2020, 11:44 UTC
0 reputation · 15 May 2020, 11:44 UTC
Stylus offers two primary mechanisms for reusing style blocks: mixins and the @extend directive. Mixins allow parameterization but duplicate properties each invocation, while @extend collapses selectors into a single rule set, reducing output size at the cost of limited argument support and potential specificity complications.
When building a UI kit that must stay under a strict CSS payload threshold, developers face an unresolved decision: should they favor mixins for their flexibility or @extend for its leaner output? The choice is further complicated by cross‑file @extend resolution rules and the lack of tree‑shaking for unused mixins.
@extend produce a smaller final CSS file than an equivalent mixin implementation?@extend chains across multiple selectors in large component sets?35275 reputation · 15 May 2020, 14:43 UTC
For a UI kit with many components sharing flat, static property sets, @extend on placeholder selectors usually produces smaller compiled CSS than mixins. Mixins duplicate every declaration at each call site, while @extend groups selectors into a single rule. The savings are most reliable when the extended selectors are defined before use and the reuse count is high.
If your shared blocks contain nested selectors, media queries, or parameterized values, mixins may still be safer. In those cases @extend can concatenate selectors inside at-rules and inflate specificity, which may force additional override rules and erase the size advantage.
Confirmed: Stylus mixins emit property declarations each time they are invoked. @extend merges selectors into one rule set, reducing output when the same block is reused. Stylus does not tree-shake unused mixin definitions; if a mixin is never called, its body remains in the compiled CSS. By contrast, @extend only generates CSS for selectors that actually extend another selector.
Likely and requiring verification: Complex mixins with nested rules or media queries can cause @extend selector bloat due to concatenation. Deep @extend chains can also inflate specificity, making overrides harder and potentially adding rules that counteract size savings. These effects depend on your Stylus version and project structure.
%base) keep the base rule out of the output unless extended.@extend works only when the target selector is imported before the file that extends it.@extend chains across components.@extend for static shared blocks.--compress to measure real payload impact.Create two minimal fixtures: one using a mixin across ten selectors, one using @extend on a placeholder with the same properties. Compile both and compare byte sizes.
stylus --compress mixin-test.stylus -o mixin-test.css
stylus --compress extend-test.stylus -o extend-test.css
wc -c mixin-test.css extend-test.css
Run a CSS analyzer or linter on the output to confirm that no unused rules remain. Repeat with different reuse counts to find the break-even point for your kit.
One detail changes the recommendation: do your shared style blocks include media queries or nested selectors? If yes, mixins are likely the safer default despite duplication, because @extend can concatenate selectors inside those constructs and raise specificity. If they are flat property lists, @extend is the leaner choice.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.