In a previous lesson, we learned how to use mixins as functions. Recall that functions are sections of code that can take arguments and eventually return the result of their work. In this way, we can perform operations on different numbers many times. A simple example is getting the square of any number. To do this, we need to multiply a number by itself. Let's try to do that with SASS.
To create a function in SASS, we use the keyword @function
followed by the unique name of the function. This is the name by which we will refer to the function later on.
@function square
Now we have to define the arguments of our function. An argument is a variable on which the result of a function depends. If you're familiar with mixins, you won't have any problems here. Unlike mixins, any function has parentheses after its name, even if no arguments are passed. Our squaring function takes one argument, the number that is squared. Don't forget that argument names can be arbitrary and are necessarily specified as variables.
@function square($number) {
}
We have created the definition of the function. Now it's our turn to write the body of the function, which contains all the necessary calculations.
@function square($number) {
$result: $number * $number;
}
What happened here? We created a variable $result
in which we put the result of multiplying a number by itself. Creating a variable for the result is good practice to help you figure out your code faster.
When choosing variable names, make sure that the names are clear and meaningful. It makes no sense to create variables named $abc
, $lala
and so on. Yes - it's a shortcut, but believe me, that after a week you yourself will not remember what is stored in a particular variable. You can read about naming in programming in our blog.
This is where the major differences between creating mixins and using arguments and creating a function come in. Function always returns something. Right now our function only counts, but returns nothing. This is similar to how if you are asked a question, you will find the answer, but you won't tell anyone. In order for the function to be able to tell what it has calculated, we use the @return
construct. It is followed by what we want to return. In this case, the variable $result
.
@function square($number) {
$result: $number * $number;
@return $result;
}
Now our function is completely ready. It has a name and arguments, it does operations inside itself and returns some result. It is easy enough to see that - let's try to call our function. To do this, all we have to do is specify its name and the arguments it takes.
$side: 10;
@function square($number) {
$result: $number * $number;
@return $result;
}
.square {
width: #{square($side)}px;
height: #{square($side)}px;
}
Compile our file and get the following CSS code:
.square {
width: 100px;
height: 100px;
}
The example may seem rather useless now, but over time you will learn about the various constructs that are possible to use in the body of your functions. This is a powerful tool that will save you dozens of hours in development.
In the last example, we used the @return
construct and the $result
variable, which was created at the beginning of our function body, to return the result. With such simple calculations, you may not use an additional variable, but substitute the necessary expression directly in @return
. This will reduce the amount of code. Be careful - only use expressions in @return
if you fully understand the structure of what is returned. Never chase to write the shortest possible functions. They may be difficult to maintain later on. For simple multiplication, you can use @return
all at once. Then our function will look like this:
@function square($number) {
@return $number * $number;
}
In addition to returning some value from a function, we can return other functions. In this case, the function we return will be executed first, and it is its value that will be returned. This is convenient in large projects when one function counts arguments for a second function and calls it. This way you can write functions that are short enough to be easy to read and understand.
Let's pretend that we want to square the sum of the passed arguments. All arguments must be taken modulo so that there are no negative values. If we already had a squared function before, there is no point in reintroducing it in a new function. You can just use it when returning a value. And in order to take the modulus of the number we will use the built-in function abs()
:
@function square($number) {
@return $number * $number;
}
@function abs-square-sum($number-one, $number-two) {
$number-one: abs($number-one);
$number-two: abs($number-two);
$sum: $number-one + $number-two;
@return square($sum);
}
@debug abs-square-sum(-10, 5);
The result of abs-square-sum(-10, 5)
is 225.
At first glance, it may seem that there is not much difference between using mixins and functions. Then why do we need this division? We use mixins everywhere and live in peace. We use the same syntax and don't get confused anymore.
It is necessary to distinguish for yourself when functions are used and when mixins are used. Mixins are, first and foremost, the ability to reuse CSS properties. You shouldn't try to use more logic there than necessary. Functions are used for calculations and are often not directly related to CSS.
Consider this statement using the example of increasing the font size by one and a half times. When using mixins, it might look like this:
$font-size: 16;
@mixin big-text($size) {
font-size: #{$size * 1.5}px;
}
.main {
.error {
@include big-text($font-size);
}
}
After compilation we get the following code:
.main .error {
font-size: 24px;
}
Let's perform the same transformations, but using functions.
$font-size: 16;
@function multiply-by-one-and-half($number) {
@return $number * 1.5;
}
.main {
.error {
font-size: #{multiply-by-one-and-half($font-size)}px;
}
}
The result of this function will be exactly the same. I will allow myself not to copy it :) As you can see, we got the same result, but with two different approaches. The main point of the functions is that we don't care where to do the multiplication by one and a half. This function can also be used to calculate indentation, height/width. We are not tied to any particular property or unit. This is where functions win over mixins. Always consider what the calculations are used for. Depending on that, choose to use either mixins or functions.
The Hexlet support team or other students will answer you.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.
Programming courses for beginners and experienced developers. Start training for free
Our graduates work in companies:
Sign up or sign in
Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.