SASS и Bootstrap - mixins vs. @extends

Я использую SASS порт Bootstrap, и мне интересно, есть ли разница между использованием предварительно определенных миксинов и использованием SASS @extends.

Например, если у меня есть

<div class="wrapper">
    Some content here....
</div>

есть ли разница между выполнением

.wrapper {
    @include make-row();
}

и

.wrapper {
    @extends .row;
}

Если нет никакой разницы, существуют ли другие микшины, которые не эквивалентны одному выражению @extends? Если таких миксинов нет, почему миксины даже существуют?

Ответ 1

Большая разница между @extends и mixin - это способ компиляции css. Это не похоже на простые примеры, но различия и последствия значительны и могут быть настоящей головной болью в дикой природе, если использовать ее небрежно. @extends немного похож на золото дураков, сначала выглядит отлично, но...

Посмотрите на простой пример:

@extends

.row {
    width: 50px;
}
.new-row {
    @extends .row;
}
.another-row {
    @extends .row;
}

скомпилируется в:

.row,
.new-row,
.another-row {
     width: 50px;
}

подмешать

@mixin row() {
    width: 50px;
}
.new-row {
    @include row();
}
.another-row {
    @include row();
}

скомпилируется в:

.new-row {
   width: 50px;
}
.another-row {
   width: 50px;
}

Mixin включает в себя свойства везде, где он попал - копирование их каждый раз, тогда как @extends группирует селектора и определяет свойства один раз. Это не сразу очевидно, потому что разница в скомпилированном css, но имеет некоторые важные последствия:

Порядок загрузки

С @extends селектора будут сгруппированы в первой точке сасс, где они встречаются, что может привести к некоторому странному переезду. Если вы определяете селектор и используете @extend для ввода свойства и пытаетесь переопределить свойство, определенное ранее в вашем sass, но после того, как расширенные свойства сгруппированы в css, переопределение не будет работать. Это может быть довольно озадачивающим.

Рассмотрим этот логически упорядоченный набор определений css и вероятный HTML: <div class='row highlight-row'></div>:

.red-text {
    color: red;
}
.row {
    color: green;
}
.highlight-row {
    @extend .red-text;
}

скомпилируется в:

.red-text,
.highlight-row {
    color: red;
}
.row {
    color: green;
}

Итак, хотя упорядочение sass делает его похожим на то, что цвет строки будет красным, скомпилированный css сделает его зеленым

Бедные группы

@extend может привести к плохо сгруппированным селекторам в результате css. Вы можете получить тридцать или сорок несвязанных вещей, которые, например, используют одно и то же свойство. Использование @extends для шрифтов - хороший пример этого.

Вложение

Если вы используете глубоко вложенный sass (что не очень хорошо, btw), и вы используете @extends, вы будете дублировать полностью вложенный селектор для каждого @extends, который вы используете, в результате чего раздутый css. Я видел это много:

.selector-1 .selector-2 .selector-3 .selector-4,
.selector-1 .selector-2 .selector-3 .selector-4 a,
.selector-1 .selector-2 .selector-3 .selector-4 li,
.selector-1 .selector-2 .selector-3 .selector-4 td {
    font-family: ariel;
}

Если вы новичок в SASS, он платит, чтобы посмотреть на скомпилированный css.

Запросы для СМИ

@extends не работают внутри медиа-запросов, потому что медиа-запросы не являются селекторами.

Заключение

Мое правило состоит в использовании @extends над mixin, если у вас нет параметров и, если вы можете разумно определить @extends и поделиться им среди нескольких тесно связанных селекторов, которые существуют поблизости например, в том же файле, который определяет модуль sass. Кнопки - хороший пример хорошо используемого @extends:

%button {
    padding: 10px;
}
.call-to-action {
    @extend %button;
    background-color: $green;
}
.submit {
    @extend %button;
    background-color: $grey;
}

Лучшая статья, чтобы помочь сделать выбор здесь

PS, знак % - это использование placeholder extends