Chepter 9: Sass Functions
Sass Functions — the part where Sass starts feeling like a real programming language inside your stylesheets.
We’re going to treat this like a hands-on coding session: first understand built-ins (what Sass gives you for free), then learn how to write your own custom @functions, with lots of practical examples, arguments, returns, control flow, and 2026 modern tips (Dart Sass reality, module system, deprecations).
1. What Are Sass Functions? (The Big Picture)
Sass functions are reusable pieces of logic that take input(s), do calculations / transformations, and return a single value.
- They compute things (colors, sizes, strings, lists…)
- They return values (not output CSS rules like mixins do)
- You call them like normal SassScript expressions: darken($color, 15%)
- Built-ins are in modules like sass:color, sass:math, sass:string, sass:list, sass:map…
- You can write your own with @function
Key difference from mixins:
| Feature | Functions (@function) | Mixins (@mixin) |
|---|---|---|
| Purpose | Compute & return one value | Output CSS declarations |
| Called with | In expressions: func($arg) | @include func(); |
| Can have @return | Yes (required) | No (optional with @content) |
| Use case | Color math, string manipulation, utils | Reusable style blocks, parametric CSS |
Functions → values Mixins → styles
2. Built-in Functions – The Ones You Use Every Day (2026 Module Style)
In modern Dart Sass (1.95+ as of Feb 2026), load modules explicitly with @use ‘sass:…’; — globals are deprecated for most.
Common modules & favorites:
|
0 1 2 3 4 5 6 7 8 9 10 |
@use 'sass:math'; @use 'sass:color'; @use 'sass:string'; @use 'sass:list'; @use 'sass:map'; |
Examples:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
// Colors – super useful for themes $primary: #6c5ce7; button { background: color.adjust($primary, $lightness: -10%); border-color: color.scale($primary, $lightness: -15%); box-shadow: 0 4px 12px color.adjust(black, $alpha: -0.92); } // Math $base-spacing: 16px; .container { padding: math.div(40px, $base-spacing) * $base-spacing; // → 2.5 * 16px = 40px gap: math.clamp(1rem, 4vw, 3rem); // responsive clamp } // Strings $font-family: "Inter", sans-serif; .heading { font-family: string.unquote($font-family); // removes quotes if needed } // Lists & Maps $spacings: 8px 16px 24px 32px; .margin-top-2 { margin-top: list.nth($spacings, 2); // 16px } |
Pro tip 2026:
- Use color.adjust() / color.scale() instead of old darken(), lighten() (deprecated in favor of CSS Color 4 compat since ~1.79)
- math.div() for division (old / can be ambiguous now)
- if() Sass function is deprecated in 1.95+ → use ternary: condition ? true-value : false-value
3. Writing Your Own Custom Functions – @function Syntax
Syntax:
|
0 1 2 3 4 5 6 7 8 9 |
@function name($param1, $param2: default, $param3...) { // logic, if/else, loops, calculations... @return some-value; } |
Must have @return — otherwise error!
Example 1: Simple spacing calculator
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
@function spacing($multiplier, $base: 16px) { @return math.round($multiplier * $base); } .card { padding: spacing(1.5); // 24px margin-bottom: spacing(3); // 48px } |
Example 2: Ratio-based font size (modular scale)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
@function scale($level, $base: 1rem, $ratio: 1.25) { @return $base * math.pow($ratio, $level); } h1 { font-size: scale(3); } // 1 * 1.25³ ≈ 1.953rem h2 { font-size: scale(2); } // ≈ 1.563rem body { font-size: scale(0); } // 1rem |
Example 3: Strip unit (very common utility)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@function strip-unit($number) { @if math.is-unitless($number) { @return $number; } @else { @return math.div($number, $number * 0 + 1); // trick to strip unit } } $font-size-px: 18px; $font-size-rem: strip-unit($font-size-px) / 16; // 1.125 |
Example 4: Advanced – Color contrast checker (simple version)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@function get-contrast-color($bg) { $lightness: color.channel($bg, "lightness"); @if $lightness > 50% { @return black; } @else { @return white; } } .alert { background: #e74c3c; color: get-contrast-color(#e74c3c); // → white } |
Example 5: Argument list (…) for flexible inputs
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@function sum($numbers...) { $total: 0; @each $num in $numbers { $total: $total + $num; } @return $total; } .total-padding: sum(10px, 20px, 5px); // 35px |
4. Modern 2026 Best Practices & Gotchas
- Put custom functions in _functions.scss or _utils.scss
- Load with @use ‘functions’ as f; → call f.spacing(2)
- Or @use ‘functions’ as *; for globals (convenient but less traceable)
- Use keyword arguments when >2–3 params
- Return typed values (color, number, string…) — helps debugging
- Avoid side effects — functions should be pure (same input → same output)
- For higher-order functions: use meta.get-function() + meta.call()
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@use 'sass:meta'; @function apply-to-each($list, $func-name) { $result: (); $fn: meta.get-function($func-name); @each $item in $list { $result: list.append($result, meta.call($fn, $item)); } @return $result; } |
- Deprecations to watch: if() function → use ternary instead
- No direct way to return multiple values → return list/map
5. Quick Challenge – Write This!
Create a function that returns a fluid font size using clamp():
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
@function fluid-font($min, $preferred, $max) { @return clamp($min, $preferred, $max); } body { font-size: fluid-font(14px, 2.5vw + 0.5rem, 24px); } |
Compile → see beautiful responsive typography!
You’ve now unlocked Sass functions — this is where you can build powerful design tokens, utilities, and theme logic.
Next — want to combine functions with maps for full theme switching? Or build a complete typography scale system with custom functions? Or explore sass:meta for advanced tricks?
Just tell me — we’re deep in Sass territory now! 🚀
