Зарегистрируйтесь, чтобы продолжить обучение

Миксины как функции SASS: Программирование

Возможно главной особенностью миксинов является то, что они могут принимать аргументы, которые могут быть использованы внутри. В программировании такие участки кода называются функциями. Они призваны облегчить переиспользование кода. Как же нам использовать это в SASS? Возьмём простой класс mx-10, который делает отступы слева и справа на 10 пикселей.

.mx-10 {
  margin-right: 10px;
  margin-left: 10px;
}

Что делать, если мы захотим добавить больше таких классов? Например mx-5, mx-10, mx-15, mx-20 и так далее. Конечно можно руками прописать все нужные нам классы и задать им свойства. Но это достаточно монотонный и долгий процесс. Попробуем для начала вынести свойства margin-left и margin-right в миксин, чтобы не было необходимости каждый раз их указывать.

@mixin margin-x {
  margin-right: 10px;
  margin-left: 10px;
}

.mx-10 {
  @include margin-x;
}

Кажется, что мало того, что ничего особо не поменялось, так мы ещё и добавили лишний код. Как нам это поможет в выносе дублирующего кода? Тут на сцену и выходит особенность миксинов принимать аргументы. Аргумент — некая переменная, от которой зависит результат выполнения функции. Аргументы указываются в круглых скобках и могут иметь любое имя. Каждый аргумент указывается с ключевым символом $. Если аргументов несколько, то они перечисляются через запятую. Добавим два аргумента в наш миксин. Первый аргумент будет указывать на значение свойства margin-right, а второй аргумент на значение свойства margin-left.

@mixin margin-x($mr, $ml) {
  margin-right: 10px;
  margin-left: 10px;
}

.mx-10 {
  @include margin-x;
}

Вторым шагом по превращению простого миксина в функцию является подстановка аргументов в свойства внутри миксина. Для этого вместо значений свойств подставим нужные нам аргументы.

@mixin margin-x($mr, $ml) {
  margin-right: $mr;
  margin-left: $ml;
}

.mx-10 {
  @include margin-x;
}

Если попробовать сейчас скомпилировать этот код, то получим следующую ошибку:

Error: Missing argument $mr.
  ╷
7 │   @include margin-x;
  │   ^^^^^^^^^^^^^^^^^^^
  ╵

Препроцессор сообщает нам, что отсутствует аргумент $mr. Это значит, что как только мы в миксин добавляем аргументы, то вызов без них невозможен. Даже если сами аргументы не будут использованы в миксине. Поправим ошибку и добавим 2 аргумента при вызове миксина. Аргументы также указываются в круглых скобках и туда мы помещаем то значение, которое ожидаем. В данном случае 10px.

@mixin margin-x($mr, $ml) {
  margin-right: $mr;
  margin-left: $ml;
}

.mx-10 {
  @include margin-x(10px, 10px);
}

После компиляции мы получим именно тот код, который и хотели получить с самого начала:

.mx-10 {
  margin-right: 10px;
  margin-left: 10px;
}

Разница теперь в том, что мы можем удобно писать новые классы без постоянного дублирования свойств.

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

А в данном случае, так как значения свойств у нас повторяются, то мы можем передавать всего один аргумент и использовать его в двух свойствах сразу.

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

Это хорошая практика, если свойства «родственны» друг другу. Использовать один аргумент для передачи, например, свойства height и margin-top не очень хорошая идея, даже если они и имеют одно значение. Так вы внесёте путаницу в код и уменьшите собственные возможности по кастомизации селекторов.

В прошлом примере было показано, что случится, если не указать аргумент при вызове миксина. На самом деле это не всегда вызовет ошибку, так как миксины могут принимать аргументы по умолчанию. Если при вызове миксина не было указано никаких аргументов, то препроцессор будет пользоваться именно ими. Эти аргументы указываются непосредственно при создании миксина и перечислении аргументов. Всё, что нам нужно — указать значения, как у простой переменной. Это схоже с тем, как у переменной устанавливался флаг !default.

@mixin margin-x($margin: 10px) {
  margin-right: $margin;
  margin-left: $margin;
}

.mx-10 {
  @include margin-x();
}

Так как мы не указали аргументы при вызове миксина, то компилятор заберёт значение по умолчанию, которое было указано при создании миксина. После компиляции получится следующий CSS-код:

.mx-10 {
  margin-right: 10px;
  margin-left: 10px;
}

Использование возможности миксинов принимать аргументы сильно помогает при создании шаблонов свойств с вендорными префиксами. В уроке миксины мы посмотрели, как сделать миксин со свойством box-shadow и его вендорными префиксами:

@mixin box-shadow-prefix {
  -webkit-box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);
  -moz-box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);
  box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);
}

.box-shadow {
  @include box-shadow-prefix;
}

Использовав возможность указывать аргументы, мы можем сильно сократить наш код при повторном использовании с другими значениями:

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

После компиляции мы получим следующий 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;
}

Передача свойств в миксин

Помимо аргументов, в миксин мы можем передавать целый CSS-код. Это очень удобно, если помимо каких-то значений нам нужно работать с кастомным CSS, который изначально отстутствует в миксине.

Передать контент в миксин можно следующим образом:

@include mixin-name($arg1, $arg2) {
  // Контент, который будет передан в миксин.
}

Получить этот контент внутри миксина можно с помощью конструкции @content, которая возьмёт всё тело из вызова миксина и добавит его туда, где была указана конструкция @content.

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

После компиляции мы получим следующий CSS код:

.btn {
  display: block;
  padding: 20px;
  font-weight: bold;
  font-size: 0.8em;
  color: #333;
}

.btn.btn-blue {
  background: #42a5f5;
  color: #fff;
}

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»