Perhaps the main feature of mixins is that they can accept arguments that can be used internally. In programming, such portions of code are called functions. They are designed to make it easier to reuse the code. So how do we use this in SASS? Let's take a simple class mx-10
that indents left and right by 10 pixels.
.mx-10 {
margin-right: 10px;
margin-left: 10px;
}
What if we want to add more of these classes? For example mx-5
, mx-10
, mx-15
, mx-20
and so on. Of course, we can handwrite all the classes we need and set their properties. But this is quite a monotonous and long process. Let's first try to put the properties margin-left
and margin-right
into a muxin so that we don't have to specify them every time.
@mixin margin-x {
margin-right: 10px;
margin-left: 10px;
}
.mx-10 {
@include margin-x;
}
It seems that not only did nothing much change, but we also added extra code. How does this help us in removing duplicate code? This is where the peculiarity of mixins to accept arguments comes into play. An argument is a variable on which the result of a function depends. Arguments are given in parentheses and can have any name. Each argument is specified with the key symbol $
. If there is more than one argument, they are listed separated by commas. Let's add two arguments to our muxin. The first argument will point to the value of the margin-right
property, and the second argument to the value of the margin-left
property.
@mixin margin-x($mr, $ml) {
margin-right: 10px;
margin-left: 10px;
}
.mx-10 {
@include margin-x;
}
The second step to turn a simple myxin into a function is to substitute arguments for the properties within the myxin. To do this, we substitute the arguments we need instead of the values of the properties.
@mixin margin-x($mr, $ml) {
margin-right: $mr;
margin-left: $ml;
}
.mx-10 {
@include margin-x;
}
If we try to compile this code now, we get the following error:
Error: Missing argument $mr.
╷
7 │ @include margin-x;
│ ^^^^^^^^^^^^^^^^^^^
╵
The preprocessor tells us that the argument $mr
is missing. This means that once we add arguments to the mixin, it is not possible to call without them. Even if the arguments themselves will not be used in the mixin. Let's correct the error and add 2 arguments when calling the myxin. The arguments are also specified in parentheses and there we put the value we expect. In this case 10px
.
@mixin margin-x($mr, $ml) {
margin-right: $mr;
margin-left: $ml;
}
.mx-10 {
@include margin-x(10px, 10px);
}
After compiling, we get exactly the code we wanted from the beginning:
.mx-10 {
margin-right: 10px;
margin-left: 10px;
}
The difference now is that we can conveniently write new classes without constantly duplicating properties.
@mixin margin-x($mr, $ml) {
margin-right: $mr;
margin-left: $ml;
}
.mx-10 {
@include margin-x(10px, 10px);
}
.mx-15 {
@include margin-x(15px, 15px);
}
.mx-20 {
@include margin-x(20px, 20px);
}
.mx-25 {
@include margin-x(25px, 25px);
}
And in this case, since we have repetitive property values, we can pass just one argument and use it in two properties at once.
@mixin margin-x($margin) {
margin-right: $margin;
margin-left: $margin;
}
.mx-10 {
@include margin-x(10px);
}
.mx-15 {
@include margin-x(15px);
}
.mx-20 {
@include margin-x(20px);
}
.mx-25 {
@include margin-x(25px);
}
This is good practice if the properties are "related" to each other. Using the same argument to pass, for example, the height
and margin-top
properties is not a good idea, even if they have the same value. You'll confuse the code and reduce your own customization options for the selectors.
The last example showed what happens if you don't specify an argument when you call a myxin. In fact, this will not always cause an error, because mixins can take arguments by default. If no arguments were specified when calling the myxin, that is what the preprocessor will use. These arguments are specified directly when creating the myxin and listing the arguments. All we have to do is specify values, like a simple variable. This is similar to how the !default' flag was set for a variable.
@mixin margin-x($margin: 10px) {
margin-right: $margin;
margin-left: $margin;
}
.mx-10 {
@include margin-x();
}
Since we didn't specify any arguments when calling the myxin, the compiler will take the default value that was specified when we created the myxin. After compiling we'll get the following CSS code:
.mx-10 {
margin-right: 10px;
margin-left: 10px;
}
Using the ability of myxins to accept arguments helps a lot when creating property templates with vendor prefixes. In the last lesson we saw how to make a mixin with the box-shadow
property and its vendor prefixes. By using the ability to specify arguments, we can greatly reduce our code when reusing it with other values.
@mixin box-shadow-prefix($value) {
-webkit-box-shadow: $value;
-moz-box-shadow: $value;
box-shadow: $value;
}
.box-shadow-small {
@include box-shadow-prefix(3px 3px 3px 0 rgba(204, 204, 204, 1));
}
.box-shadow-medium {
@include box-shadow-prefix(7px 7px 3px 0 rgba(204, 204, 204, 1));
}
.box-shadow-big {
@include box-shadow-prefix(10px 10px 3px 0 rgba(204, 204, 204, 1));
}
After compiling we get the following CSS:
.box-shadow-small {
-webkit-box-shadow: 3px 3px 3px 0 #cccccc;
-moz-box-shadow: 3px 3px 3px 0 #cccccc;
box-shadow: 3px 3px 3px 0 #cccccc;
}
.box-shadow-medium {
-webkit-box-shadow: 7px 7px 3px 0 #cccccc;
-moz-box-shadow: 7px 7px 3px 0 #cccccc;
box-shadow: 7px 7px 3px 0 #cccccc;
}
.box-shadow-big {
-webkit-box-shadow: 10px 10px 3px 0 #cccccc;
-moz-box-shadow: 10px 10px 3px 0 #cccccc;
box-shadow: 10px 10px 3px 0 #cccccc;
}
In addition to arguments, we can pass entire CSS code to the myxin. This is very useful if in addition to some values we need to work with custom CSS, which initially is absent in the mixin.
You can transfer content to the myxin as follows:
@include mixin-name($arg1, $arg2) {
// Content to be transferred to the myxin.
}
You can get this content inside the myxin by using the @content
construct, which will take the entire body from the myxin call and add it to where the @content
construct was specified.
@mixin btn {
display: block;
padding: 20px;
font-weight: bold;
font-size: 0.8em;
color: #333;
@content;
}
.btn {
@include btn {
&.btn-blue {
background: #42a5f5;
color: #fff;
}
}
}
After compiling, we get the following CSS code:
.btn {
display: block;
padding: 20px;
font-weight: bold;
font-size: 0.8em;
color: #333;
}
.btn.btn-blue {
background: #42a5f5;
color: #fff;
}
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.