Register to get access to free programming courses with interactive exercises

Mixins as functions SASS: Programming

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;
}

Transferring properties in the myxin

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;
}

Hexlet Experts

Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

For full access to the course you need a professional subscription.

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.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.bookmate">Bookmate</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.healthsamurai">Healthsamurai</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.dualboot">Dualboot</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.abbyy">Abbyy</span>
Suggested learning programs
profession
Layout with the latest CSS standards
5 months
from scratch
under development
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

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.