mirror of
https://github.com/danog/sass-site.git
synced 2024-12-15 02:47:36 +01:00
361 lines
12 KiB
Plaintext
361 lines
12 KiB
Plaintext
---
|
|
title: "@function"
|
|
table_of_contents: true
|
|
introduction: >
|
|
Functions allow you to define complex operations on [SassScript
|
|
values](/documentation/values) that you can re-use throughout your stylesheet.
|
|
They make it easy to abstract out common formulas and behaviors in a readable
|
|
way.
|
|
---
|
|
|
|
{% markdown %}
|
|
Functions are defined using the `@function` at-rule, which is written
|
|
`@function <name>(<arguments...>) { ... }`. A function's name can be any Sass
|
|
identifier. It can only contain [universal statements][], as well as the
|
|
[`@return` at-rule][] which indicates the value to use as the result of the
|
|
function call. Functions are called using the normal CSS function syntax.
|
|
|
|
[universal statements]: /documentation/syntax/structure#universal-statements
|
|
[`@return` at-rule]: #return
|
|
{% endmarkdown %}
|
|
|
|
{% codeExample 'functions' %}
|
|
@function pow($base, $exponent) {
|
|
$result: 1;
|
|
@for $_ from 1 through $exponent {
|
|
$result: $result * $base;
|
|
}
|
|
@return $result;
|
|
}
|
|
|
|
.sidebar {
|
|
float: left;
|
|
margin-left: pow(4, 3) * 1px;
|
|
}
|
|
===
|
|
@function pow($base, $exponent)
|
|
$result: 1
|
|
@for $_ from 1 through $exponent
|
|
$result: $result * $base
|
|
|
|
@return $result
|
|
|
|
|
|
.sidebar
|
|
float: left
|
|
margin-left: pow(4, 3) * 1px
|
|
{% endcodeExample %}
|
|
|
|
{% funFact %}
|
|
Function names, like all Sass identifiers, treat hyphens and underscores as
|
|
identical. This means that `scale-color` and `scale_color` both refer to the
|
|
same function. This is a historical holdover from the very early days of Sass,
|
|
when it *only* allowed underscores in identifier names. Once Sass added
|
|
support for hyphens to match CSS's syntax, the two were made equivalent to
|
|
make migration easier.
|
|
{% endfunFact %}
|
|
|
|
{% headsUp %}
|
|
While it's technically possible for functions to have side-effects like
|
|
setting [global variables][], this is strongly discouraged. Use [mixins][] for
|
|
side-effects, and use functions just to compute values.
|
|
|
|
[global variables]: /documentation/variables#scope
|
|
[mixins]: /documentation/at-rules/mixin
|
|
{% endheadsUp %}
|
|
|
|
{% markdown %}
|
|
## Arguments
|
|
|
|
{% comment %}
|
|
When changing this section, don't forget to change the mixin arguments
|
|
section as well!
|
|
{% endcomment %}
|
|
|
|
Arguments allow functions' behavior to be customized each time they're called.
|
|
The arguments are specified in the `@function` rule after the function's name,
|
|
as a list of variable names surrounded by parentheses. The function must be
|
|
called with the same number of arguments in the form of [SassScript
|
|
expressions][]. The values of these expression are available within the
|
|
function's body as the corresponding variables.
|
|
|
|
[SassScript expressions]: /documentation/syntax/structure#expressions
|
|
|
|
{% funFact %}
|
|
Argument lists can also have trailing commas! This makes it easier to avoid
|
|
syntax errors when refactoring your stylesheets.
|
|
{% endfunFact %}
|
|
|
|
### Optional Arguments
|
|
|
|
Normally, every argument a function declares must be passed when that function
|
|
is included. However, you can make an argument optional by defining a *default
|
|
value* which will be used if that arguments isn't passed. Default values use
|
|
the same syntax as [variable declarations][]: the variable name, followed by a
|
|
colon and a [SassScript expression][]. This makes it easy to define flexible
|
|
function APIs that can be used in simple or complex ways.
|
|
|
|
[variable declarations]: /documentation/variables
|
|
[SassScript expression]: /documentation/syntax/structure#expressions
|
|
{% endmarkdown %}
|
|
|
|
{% codeExample 'optional-arguments' %}
|
|
@function invert($color, $amount: 100%) {
|
|
$inverse: change-color($color, $hue: hue($color) + 180);
|
|
@return mix($inverse, $color, $amount);
|
|
}
|
|
|
|
$primary-color: #036;
|
|
.header {
|
|
background-color: invert($primary-color, 80%);
|
|
}
|
|
===
|
|
@function invert($color, $amount: 100%)
|
|
$inverse: change-color($color, $hue: hue($color) + 180)
|
|
@return mix($inverse, $color, $amount)
|
|
|
|
|
|
$primary-color: #036
|
|
.header
|
|
background-color: invert($primary-color, 80%)
|
|
{% endcodeExample %}
|
|
|
|
{% funFact %}
|
|
Default values can be any SassScript expression, and they can even refer to
|
|
earlier arguments!
|
|
{% endfunFact %}
|
|
|
|
{% markdown %}
|
|
### Keyword Arguments
|
|
|
|
When a function is called, arguments can be passed by name in addition to
|
|
passing them by their position in the argument list. This is especially useful
|
|
for functions with multiple optional arguments, or with [boolean][] arguments
|
|
whose meanings aren't obvious without a name to go with them. Keyword
|
|
arguments use the same syntax as [variable declarations][] and [optional
|
|
arguments][].
|
|
|
|
[variable declarations]: /documentation/variables
|
|
[boolean]: /documentation/values/booleans
|
|
[optional arguments]: #optional-arguments
|
|
{% endmarkdown %}
|
|
|
|
{% codeExample 'keyword-arguments' %}
|
|
$primary-color: #036;
|
|
.banner {
|
|
background-color: $primary-color;
|
|
color: scale-color($primary-color, $lightness: +40%);
|
|
}
|
|
===
|
|
$primary-color: #036
|
|
.banner
|
|
background-color: $primary-color
|
|
color: scale-color($primary-color, $lightness: +40%)
|
|
{% endcodeExample %}
|
|
|
|
{% headsUp %}
|
|
Because *any* argument can be passed by name, be careful when renaming a
|
|
function's arguments... it might break your users! It can be helpful to keep
|
|
the old name around as an [optional argument][] for a while and printing a
|
|
[warning][] if anyone passes it, so they know to migrate to the new argument.
|
|
|
|
[optional argument]: #optional-arguments
|
|
[warning]: /documentation/at-rules/warn
|
|
{% endheadsUp %}
|
|
|
|
{% markdown %}
|
|
### Taking Arbitrary Arguments
|
|
|
|
Sometimes it's useful for a function to be able to take any number of
|
|
arguments. If the last argument in a `@function` declaration ends in `...`,
|
|
then all extra arguments to that function are passed to that argument as a
|
|
[list][]. This argument is known as an [argument list][].
|
|
|
|
[list]: /documentation/values/lists
|
|
[argument list]: /documentation/values/lists#argument-lists
|
|
{% endmarkdown %}
|
|
|
|
{% codeExample 'taking-arbitrary-arguments' %}
|
|
@function sum($numbers...) {
|
|
$sum: 0;
|
|
@each $number in $numbers {
|
|
$sum: $sum + $number;
|
|
}
|
|
@return $sum;
|
|
}
|
|
|
|
.micro {
|
|
width: sum(50px, 30px, 100px);
|
|
}
|
|
===
|
|
@function sum($numbers...)
|
|
$sum: 0
|
|
@each $number in $numbers
|
|
$sum: $sum + $number
|
|
|
|
@return $sum
|
|
|
|
|
|
.micro
|
|
width: sum(50px, 30px, 100px)
|
|
{% endcodeExample %}
|
|
|
|
{% markdown %}
|
|
#### Taking Arbitrary Keyword Arguments
|
|
|
|
Argument lists can also be used to take arbitrary keyword arguments. The
|
|
[`meta.keywords()` function][] takes an argument list and returns any extra
|
|
keywords that were passed to the function as a [map][] from argument names
|
|
(not including `$`) to those arguments' values.
|
|
|
|
[`meta.keywords()` function]: /documentation/modules/meta#keywords
|
|
[map]: /documentation/values/maps
|
|
|
|
{% funFact %}
|
|
If you don't ever pass an argument list to the [`meta.keywords()`
|
|
function][], that argument list won't allow extra keyword arguments. This
|
|
helps callers of your function make sure they haven't accidentally
|
|
misspelled any argument names.
|
|
|
|
[`meta.keywords()` function]: /documentation/modules/meta#keywords
|
|
{% endfunFact %}
|
|
|
|
#### Passing Arbitrary Arguments
|
|
|
|
Just like argument lists allow functions to take arbitrary positional or
|
|
keyword arguments, the same syntax can be used to *pass* positional and
|
|
keyword arguments to a function. If you pass a list followed by `...` as the
|
|
last argument of a function call, its elements will be treated as additional
|
|
positional arguments. Similarly, a map followed by `...` will be treated as
|
|
additional keyword arguments. You can even pass both at once!
|
|
{% endmarkdown %}
|
|
|
|
{% codeExample 'passing-arbitrary-arguments' %}
|
|
$widths: 50px, 30px, 100px;
|
|
.micro {
|
|
width: min($widths...);
|
|
}
|
|
===
|
|
$widths: 50px, 30px, 100px
|
|
.micro
|
|
width: min($widths...)
|
|
{% endcodeExample %}
|
|
|
|
{% funFact false %}
|
|
{% markdown %}
|
|
Because an [argument list][] keeps track of both positional and keyword
|
|
arguments, you use it to pass both at once to another function. That makes
|
|
it super easy to define an alias for a function!
|
|
|
|
[argument list]: /documentation/values/lists#argument-lists
|
|
{% endmarkdown %}
|
|
|
|
{% codeExample 'passing-arbitrary-arguments-fun-fact' %}
|
|
@function fg($args...) {
|
|
@warn "The fg() function is deprecated. Call foreground() instead.";
|
|
@return foreground($args...);
|
|
}
|
|
===
|
|
@function fg($args...)
|
|
@warn "The fg() function is deprecated. Call foreground() instead."
|
|
@return foreground($args...)
|
|
{% endcodeExample %}
|
|
{% endfunFact %}
|
|
|
|
{% markdown %}
|
|
## `@return`
|
|
|
|
The `@return` at-rule indicates the value to use as the result of calling a
|
|
function. It's only allowed within a `@function` body, and each `@function`
|
|
must end with a `@return`.
|
|
|
|
When a `@return` is encountered, it immediately ends the function and returns
|
|
its result. Returning early can be useful for handling edge-cases or cases
|
|
where a more efficient algorithm is available without wrapping the entire
|
|
function in an [`@else` block][].
|
|
|
|
[`@else` block]: /documentation/at-rules/control/if#else
|
|
{% endmarkdown %}
|
|
|
|
{% codeExample 'return', false %}
|
|
@use "sass:string";
|
|
|
|
@function str-insert($string, $insert, $index) {
|
|
// Avoid making new strings if we don't need to.
|
|
@if string.length($string) == 0 {
|
|
@return $insert;
|
|
}
|
|
|
|
$before: string.slice($string, 0, $index);
|
|
$after: string.slice($string, $index);
|
|
@return $before + $insert + $after;
|
|
}
|
|
===
|
|
@use "sass:string"
|
|
|
|
@function str-insert($string, $insert, $index)
|
|
// Avoid making new strings if we don't need to.
|
|
@if string.length($string) == 0
|
|
@return $insert
|
|
|
|
|
|
$before: string.slice($string, 0, $index)
|
|
$after: string.slice($string, $index)
|
|
@return $before + $insert + $after
|
|
{% endcodeExample %}
|
|
|
|
{% markdown %}
|
|
## Other Functions
|
|
|
|
In addition to user-defined function, Sass provides a substantial [core
|
|
library][] of built-in functions that are always available to use. Sass
|
|
implementations also make it possible to define [custom functions][] in the
|
|
host language. And of course, you can always call [plain CSS functions][]
|
|
(even ones with [weird syntax][]).
|
|
|
|
[core library]: /documentation/modules
|
|
[custom functions]: /documentation/js-api/interfaces/LegacySharedOptions#functions
|
|
[plain CSS functions]: #plain-css-functions
|
|
[weird syntax]: /documentation/syntax/special-functions
|
|
|
|
### Plain CSS Functions
|
|
|
|
Any function call that's not either a user-defined or
|
|
[built-in](/documentation/modules) function is compiled to a plain CSS
|
|
function (unless it uses [Sass argument
|
|
syntax](/documentation/at-rules/function#arguments)). The arguments will be
|
|
compiled to CSS and included as-is in the function call. This ensures that
|
|
Sass supports all CSS functions without needing to release new versions every
|
|
time a new one is added.
|
|
{% endmarkdown %}
|
|
|
|
{% codeExample 'plain-css-functions', false %}
|
|
@debug var(--main-bg-color); // var(--main-bg-color)
|
|
|
|
$primary: #f2ece4;
|
|
$accent: #e1d7d2;
|
|
@debug radial-gradient($primary, $accent); // radial-gradient(#f2ece4, #e1d7d2)
|
|
===
|
|
@debug var(--main-bg-color) // var(--main-bg-color)
|
|
|
|
$primary: #f2ece4
|
|
$accent: #e1d7d2
|
|
@debug radial-gradient($primary, $accent) // radial-gradient(#f2ece4, #e1d7d2)
|
|
{% endcodeExample %}
|
|
|
|
{% headsUp %}
|
|
Because any unknown function will be compiled to CSS, it's easy to miss when
|
|
you typo a function name. Consider running a [CSS linter][] on your
|
|
stylesheet's output to be notified when this happens!
|
|
|
|
[CSS linter]: https://stylelint.io/
|
|
{% endheadsUp %}
|
|
|
|
{% funFact %}
|
|
Some CSS functions, like `calc()` and `element()` have unusual syntax. Sass
|
|
[parses these functions specially][] as [unquoted strings][].
|
|
|
|
[parses these functions specially]: /documentation/syntax/special-functions
|
|
[unquoted strings]: /documentation/values/strings#unquoted
|
|
{% endfunFact %}
|