Functions and Built-in Function Reference

1. Custom Function Definition with @function

Feature Syntax Description Example
Function Definition @function name() { } Declares reusable function @function double($n) { @return $n * 2; }
@return Directive @return value; Returns computed value Must have at least one return
Parameters $param1, $param2 Function arguments Can have defaults like mixins
Function Call name($args) Invokes function width: double(10px);
Scope Variables local to function Isolated scope Local vars don't leak outside
Naming Kebab-case or camelCase Descriptive, verb-based calculate-rem(), lighten-color()

Example: Custom function basics

// Simple calculation function
@function strip-unit($number) {
  @if type-of($number) == 'number' and not unitless($number) {
    @return $number / ($number * 0 + 1);
  }
  @return $number;
}

// Usage
$value: strip-unit(16px);  // Returns: 16

// Function with multiple parameters
@function calculate-rem($size, $base: 16px) {
  $rem: $size / $base;
  @return #{$rem}rem;
}

// Usage
font-size: calculate-rem(24px);       // 1.5rem
font-size: calculate-rem(20px, 10px); // 2rem

// Conditional return
@function contrast-color($color) {
  @if (lightness($color) > 50%) {
    @return #000;
  } @else {
    @return #fff;
  }
}

.button {
  background: #3498db;
  color: contrast-color(#3498db);  // Returns: #fff
}

2. Function Arguments and Return Values

Feature Syntax Behavior Use Case
Required Arguments @function fn($arg) Must be provided Essential parameters
Default Arguments @function fn($arg: val) Optional with fallback Common use cases
Variadic Arguments @function fn($args...) Accept unlimited args Flexible parameters
Named Arguments fn($name: value) Explicit parameter naming Clarity, skip defaults
Return Type Any Sass data type Numbers, strings, colors, lists, maps, null Flexible output
Multiple Returns Conditional @return Branch-based returns Complex logic
Early Return @return exits function Stops execution Guard clauses

Example: Advanced function arguments

// Variadic arguments
@function sum($numbers...) {
  $total: 0;
  @each $num in $numbers {
    $total: $total + $num;
  }
  @return $total;
}

$result: sum(1, 2, 3, 4, 5);  // 15

// Named arguments for clarity
@function responsive-size(
  $min-size,
  $max-size,
  $min-viewport: 320px,
  $max-viewport: 1200px
) {
  $slope: ($max-size - $min-size) / ($max-viewport - $min-viewport);
  $intercept: $min-size - $slope * $min-viewport;
  @return calc(#{$intercept} + #{$slope * 100vw});
}

// Call with named args
font-size: responsive-size(
  $min-size: 14px,
  $max-size: 18px
);

// Guard clauses with early return
@function safe-divide($dividend, $divisor) {
  @if $divisor == 0 {
    @warn "Cannot divide by zero";
    @return null;
  }
  @return $dividend / $divisor;
}

// Return different types
@function get-spacing($key) {
  $spacing: (small: 8px, medium: 16px, large: 24px);
  
  @if map-has-key($spacing, $key) {
    @return map-get($spacing, $key);  // Returns number
  }
  @return null;  // Returns null if not found
}

3. Built-in Color Functions (lighten, darken, mix)

Function Syntax Description Example
lighten() lighten($color, $amount) Increases lightness by % lighten(#3498db, 20%)
darken() darken($color, $amount) Decreases lightness by % darken(#3498db, 20%)
mix() mix($c1, $c2, $weight) Blends two colors mix(#f00, #00f, 50%)
saturate() saturate($color, $amount) Increases saturation saturate(#3498db, 20%)
desaturate() desaturate($color, $amount) Decreases saturation desaturate(#3498db, 20%)
grayscale() grayscale($color) Removes all saturation grayscale(#3498db)
complement() complement($color) Returns opposite hue complement(#3498db)
invert() invert($color) Inverts RGB values invert(#3498db)
adjust-hue() adjust-hue($color, $degrees) Rotates hue on color wheel adjust-hue(#3498db, 45deg)
opacity/alpha() opacity($color) Gets alpha channel value alpha(rgba(0,0,0,0.5))
transparentize() transparentize($color, $amount) Decreases opacity transparentize(#000, 0.3)
opacify()/fade-in() opacify($color, $amount) Increases opacity opacify(rgba(0,0,0,.5), 0.2)

Example: Color manipulation functions

$primary: #3498db;

// Lightness adjustments
.light-bg {
  background: lighten($primary, 30%);  // #a8d5f2
}

.dark-bg {
  background: darken($primary, 20%);   // #1f5d87
}

// Color mixing
$brand-gradient: mix(#3498db, #9b59b6, 50%);

.gradient {
  background: linear-gradient(
    to right,
    #3498db,
    $brand-gradient,
    #9b59b6
  );
}

// Saturation
.vibrant {
  color: saturate($primary, 40%);      // More vivid
}

.muted {
  color: desaturate($primary, 40%);    // Less vivid
}

// Complementary color scheme
$accent: complement($primary);         // Opposite on color wheel

.scheme {
  background: $primary;
  color: $accent;
}

// Transparency
$overlay: transparentize(#000, 0.5);   // rgba(0, 0, 0, 0.5)

.modal-backdrop {
  background: $overlay;
}

// Advanced: Color palette generator
@function generate-palette($base-color) {
  @return (
    base: $base-color,
    light: lighten($base-color, 15%),
    lighter: lighten($base-color, 30%),
    dark: darken($base-color, 15%),
    darker: darken($base-color, 30%),
    complement: complement($base-color)
  );
}

$blue-palette: generate-palette(#3498db);
Note: Use mix() instead of lighten()/darken() for more natural color variations. Mix with white/black produces better results.

4. Built-in Math Functions (abs, ceil, floor, round)

Function Syntax Description Example
abs() abs($number) Absolute value abs(-15px)15px
ceil() ceil($number) Round up to nearest integer ceil(4.3)5
floor() floor($number) Round down to nearest integer floor(4.8)4
round() round($number) Round to nearest integer round(4.5)5
max() max($numbers...) Returns largest value max(1, 5, 3)5
min() min($numbers...) Returns smallest value min(1, 5, 3)1
percentage() percentage($number) Converts to percentage percentage(0.5)50%
random() random($limit) Random integer 1 to $limit random(100)1-100
comparable() comparable($n1, $n2) Check if units compatible comparable(1px, 1em)false

Example: Math function applications

// Responsive grid calculation
@function grid-width($cols, $total: 12) {
  $percent: ($cols / $total) * 100%;
  @return floor($percent * 100) / 100;  // Round to 2 decimals
}

.col-4 {
  width: grid-width(4);  // 33.33%
}

// Clamp value between min and max
@function clamp($value, $min, $max) {
  @return max($min, min($value, $max));
}

$size: clamp(20px, 10px, 30px);  // Returns: 20px

// Aspect ratio calculation
@function aspect-ratio-padding($width, $height) {
  @return percentage($height / $width);
}

.video-16-9 {
  padding-bottom: aspect-ratio-padding(16, 9);  // 56.25%
}

// Random color generator
@function random-color() {
  @return rgb(random(255), random(255), random(255));
}

.random-bg {
  background: random-color();
}

// Spacing scale with rounding
$base-spacing: 8px;

@function spacing($multiplier) {
  @return round($base-spacing * $multiplier);
}

.mt-1 { margin-top: spacing(1); }    // 8px
.mt-2 { margin-top: spacing(2); }    // 16px
.mt-3 { margin-top: spacing(3); }    // 24px

// Ensure non-negative values
@function positive($value) {
  @return max(0, $value);
}

.safe-margin {
  margin: positive(-10px);  // 0px (prevents negative)
}

5. String Functions (quote, unquote, str-length)

Function Syntax Description Example
quote() quote($string) Adds quotes to string quote(sans-serif)"sans-serif"
unquote() unquote($string) Removes quotes from string unquote("Arial")Arial
str-length() str-length($string) Returns character count str-length("hello")5
str-index() str-index($string, $substring) Finds position of substring str-index("hello", "ll")3
str-insert() str-insert($string, $insert, $index) Inserts string at position str-insert("hello", "X", 3)"heXllo"
str-slice() str-slice($string, $start, $end) Extracts substring str-slice("hello", 2, 4)"ell"
to-upper-case() to-upper-case($string) Converts to uppercase to-upper-case("hello")"HELLO"
to-lower-case() to-lower-case($string) Converts to lowercase to-lower-case("HELLO")"hello"
unique-id() unique-id() Generates unique string unique-id()"u1a2b3c4"

Example: String manipulation

// Font family management
$font-stack: (Helvetica, Arial, sans-serif);

@function get-font-stack($fonts) {
  $stack: '';
  @each $font in $fonts {
    @if str-index($font, ' ') {
      $stack: $stack + quote($font) + ', ';
    } @else {
      $stack: $stack + $font + ', ';
    }
  }
  @return unquote(str-slice($stack, 1, -3));
}

.text {
  font-family: get-font-stack($font-stack);
}

// String replacement function
@function str-replace($string, $search, $replace: '') {
  $index: str-index($string, $search);
  
  @if $index {
    $before: str-slice($string, 1, $index - 1);
    $after: str-slice($string, $index + str-length($search));
    @return $before + $replace + $after;
  }
  
  @return $string;
}

$url: "assets/images/icon.png";
$new-url: str-replace($url, "assets", "public");
// Result: "public/images/icon.png"

// Class name generator
@function bem-class($block, $element: null, $modifier: null) {
  $class: $block;
  
  @if $element {
    $class: $class + '__' + $element;
  }
  
  @if $modifier {
    $class: $class + '--' + $modifier;
  }
  
  @return unquote('.' + $class);
}

// Usage
#{bem-class('card', 'header', 'large')} {
  font-size: 2rem;
}
// Generates: .card__header--large { }

// Unique ID for animations
@function unique-animation-name($base) {
  @return unquote($base + '-' + unique-id());
}

$anim-name: unique-animation-name('slide');

@keyframes #{$anim-name} {
  from { opacity: 0; }
  to { opacity: 1; }
}

6. Type Checking Functions (type-of, unit, unitless)

Function Syntax Returns Example
type-of() type-of($value) Data type as string type-of(10px)"number"
unit() unit($number) Unit as string unit(10px)"px"
unitless() unitless($number) Boolean (has no unit) unitless(10)true
is-bracketed() is-bracketed($list) Boolean (list has [ ]) is-bracketed([a, b])true
is-superselector() is-superselector($s1, $s2) Boolean (s1 contains s2) is-superselector('.a .b', '.b')
variable-exists() variable-exists($name) Boolean (var defined) variable-exists(color)
global-variable-exists() global-variable-exists($name) Boolean (global var exists) Checks global scope only
function-exists() function-exists($name) Boolean (function defined) function-exists(lighten)
mixin-exists() mixin-exists($name) Boolean (mixin defined) mixin-exists(clearfix)

Example: Type checking and validation

// Robust unit conversion
@function convert-to-rem($value, $base: 16px) {
  // Type validation
  @if type-of($value) != 'number' {
    @warn "#{$value} is not a number";
    @return $value;
  }
  
  // Check if already unitless or rem
  @if unitless($value) {
    @return #{$value}rem;
  }
  
  @if unit($value) == 'rem' {
    @return $value;
  }
  
  @if unit($value) == 'px' {
    @return $value / $base * 1rem;
  }
  
  @warn "Cannot convert #{unit($value)} to rem";
  @return $value;
}

.text {
  font-size: convert-to-rem(18px);      // 1.125rem
  padding: convert-to-rem(16);          // 16rem
  margin: convert-to-rem(1.5rem);       // 1.5rem
}

// Polymorphic spacing function
@function spacing($value) {
  @if type-of($value) == 'number' {
    @return $value * 8px;
  }
  
  @if type-of($value) == 'string' {
    $map: (xs: 4px, sm: 8px, md: 16px, lg: 24px, xl: 32px);
    @if map-has-key($map, $value) {
      @return map-get($map, $value);
    }
  }
  
  @warn "Invalid spacing value: #{$value}";
  @return 0;
}

.component {
  margin: spacing(2);       // 16px (number)
  padding: spacing('lg');   // 24px (string)
}

// Conditional mixin application
@mixin apply-if-exists($mixin-name, $args...) {
  @if mixin-exists($mixin-name) {
    @include #{$mixin-name}($args...);
  } @else {
    @warn "Mixin #{$mixin-name} does not exist";
  }
}

// Safe variable getter
@function get-var($name, $fallback: null) {
  @if global-variable-exists($name) {
    @return #{$name};
  }
  @return $fallback;
}

// Type guard for lists
@function safe-nth($list, $index, $default: null) {
  @if type-of($list) != 'list' {
    @return $default;
  }
  
  @if $index <= length($list) and $index > 0 {
    @return nth($list, $index);
  }
  
  @return $default;
}

$colors: red, blue, green;
$color: safe-nth($colors, 5, black);  // Returns: black (fallback)

Function Best Practices

  • Use functions for calculations, mixins for styles
  • Always validate input types and return appropriate values
  • Provide meaningful @warn/@error messages for debugging
  • Use @return early for guard clauses and error handling
  • Document expected parameters and return types
  • Keep functions pure (no side effects, same input = same output)
  • Name functions with verbs (calculate-, get-, is-, has-)
  • Combine type checking with default parameters for robustness
Note: Modern Sass (Dart Sass) uses sass:math, sass:color, sass:string modules. Use @use "sass:math"; and math.floor() instead of global functions.