Миксины
Миксины (они же примеси) - это куски CSS кода, которые могут быть повторно использованы в любом месте CSS-документа. Они способны принимать аргументы, делая тем самым повторное их использование более гибким.
Для объявления миксинов используется директива @mixin. Объявление миксина представлено ниже.
@mixin clearfix {
&::after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
}
Так сложилось, что в именах миксинов символы нижнего подчеркивания и дефисы взаимозаменяемы. К примеру миксин text-style можно подключить как text_style и наоборот.
Для того, чтобы вызвать миксин используется директива @include. Данная директива принимает имя миксина и передаваемые в него аргументы. Передачу аргументов в миксины мы рассмотрим чуть позже.
// Сперва импортируем наш миксин если он лежит в другом файле
@import "_mixins.scss";
.wrapper {
@include clearfix;
}
.wrapper::after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
До этого моменты мы рассматривали применение миксинов в CSS-селекторах, но их можно применять и в корне документа, при условии, что они не используют ссылку на родителя и не определяют каких либо стилей. Давайте рассмотрим пример ниже.
@mixin headers {
.h1 {
color: blue
font-size: 24px
}
.h2 {
color: blue
font-size: 20px
}
}
@include headers;
.h1 {
color: blue
font-size: 24px
}
.h2 {
color: blue
font-size: 20px
}
Как видно из примера, миксин headers вставляет заголовки в выходной CSS.
Аргументы в миксинах
В миксины возможно передавать аргументы. Аргументы передаются в круглых скобках, сразу после названия миксина и разделяются между собой запятыми.
Первоначально когда вводилась новая спецификация, для CSS3 создавались миксины с разными префиксами. Были даже целые библиотеки которые создавали кроссбраузерные свойства (к примеру compass). Сейчас необходимость в этом отпала. Давайте рассмотрим старый-старый миксин для свойства border-radius.
@mixin borderRadius($value) {
-moz-border-radius: $value; /* Firefox */
-webkit-border-radius: $value; /* Safari, Chrome */
-khtml-border-radius: $value; /* KHTML */
border-radius: $value; /* CSS3 */
}
.btn {
@include borderRadius(10px);
display: inline-block;
text-decoration: none;
}
.btn {
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-khtml-border-radius: 10px;
border-radius: 10px;
display: inline-block;
text-decoration: none;
}
В миксинах так-же возможно задавать значения аргументов по умолчанию. Аргументы по умолчанию определяются так-же как и переменные. Давайте рассмотрим следующий пример.
@mixin borderRadius($value: 10px) {
-moz-border-radius: $value; /* Firefox */
-webkit-border-radius: $value; /* Safari, Chrome */
-khtml-border-radius: $value; /* KHTML */
border-radius: $value; /* CSS3 */
}
.btn {
@include borderRadius();
display: inline-block;
text-decoration: none;
}
.btn {
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-khtml-border-radius: 10px;
border-radius: 10px;
display: inline-block;
text-decoration: none;
}
Из примера видно, что при вызове миксина, мы не передали в него аргумент, как следствие компилятор SASS применил значение по умолчанию, это значение в примере равно 10px. Если вы передаете в миксин несколько аргументов, то аргументы которые используют значения по умолчанию, должны следовать после аргументов которые значения по умолчанию не используют. В JS применяется то-же правило.
@mixin styledBlock($value, $bgColor: blue, $color: #fff) {
-moz-border-radius: $value; /* Firefox */
-webkit-border-radius: $value; /* Safari, Chrome */
-khtml-border-radius: $value; /* KHTML */
border-radius: $value; /* CSS3 */
background-color: $bgColor;
color: $color;
}
.styled-block {
@include styledBlock(10px, #000);
}
.styled-block {
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-khtml-border-radius: 10px;
border-radius: 10px;
background-color: #000;
color: #fff;
}
Как видно из примера выше, в нашем миксине мы не задаем значение по умолчанию для свойства border-radius, а для свойств background-color и color, мы значения по умолчанию задаем, у нас синий фон и белый текст на нем. Пусть по умолчанию будет так. Вызвав наш миксин с 2 параметрами, мы тем самым задали значение для свойства border-radius, переопределили значение для свойства background-color. Так как третье свойство мы не задали, то оно у нас взялось по умолчанию. В итоге мы получили блок с черным фоном и белым текстом на нем. Впринципе так можно делать, но вообще лучше использовать именованные аргументы, так наш код будет более гибким. Давайте посмотрим как это можно сделать.
@mixin styledBlock($value: 10px, $bgColor: blue, $color: #fff) {
-moz-border-radius: $value; /* Firefox */
-webkit-border-radius: $value; /* Safari, Chrome */
-khtml-border-radius: $value; /* KHTML */
border-radius: $value; /* CSS3 */
background-color: $bgColor;
color: $color;
}
.styled-block {
@include styledBlock($color: #000);
}
.styled-block {
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-khtml-border-radius: 10px;
border-radius: 10px;
background-color: blue;
color: #000;
}
В примере выше мы задали значения по умолчанию для всех трех свойств. Если мы применим наш миксин без аргументов, то у нас должен получиться блок с синим фоном, белым текстом, и значение border-radius будет равно 10px, это по умолчанию. При вызове нашего миксина мы переопределили только цвет текста ($color: #000), соответственно только это свойство у нас и переопределилось. В итоге мы получаем синий блок с черным текстом и значение border-radius будет равно 10px. Что тут можно сказать, последний способ более длинный, но зато он и более понятный. По опыту могу сказать, что если вы передаете более 3 параметров, и для разных блоков разные параметры меняются, то лучше использовать именованные аргументы, и вызывать миксины с именами переопределяемых свойств.
Переменные аргументов
Иногда мы не можем знать сколько аргументов будет передано в миксин. Для этого можно воспользоваться следующим приемом.
@mixin box-shadow($borderColor, $shadows...) {
border-color: $borderColor;
-moz-box-shadow: $shadows;
-webkit-box-shadow: $shadows;
box-shadow: $shadows;
}
.shadows {
.shadows {
border-color: #000;
-moz-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
-webkit-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
}
В примере выше, мы передали последний аргумент в наш миксин следующим образом $shadows..., если дословно переводить официальную документацию, то это называется "переменные аргументов". Если называть это своими словами, то переменные аргументов должны передаваться последними в миксин. Они получают все остальные параметры и упаковывают их в список. Они выглядят как обычные, но после них ставится многоточие (правильнее сказать 3 точки). В нашем примере, первая переменная определит border-color, а все, что мы введем дальше пойдет в переменную $shadow. Так я думаю будет понятнее. Если вы знаете JS, то наверное увидели аналог со spread оператором, только три точки ставятся не в начале, а в конце аргумента. Давайте рассмотрим следующий пример.
@mixin styleFont($fontSize, $fontWeight, $fontStyle) {
font: $fontStyle $fontWeight #{$fontSize}px/120% Arial, sans-serif;
}
$val: 12, bold, italic;
.blog {
@include styleFont($val...);
}
$val-map: (fontSize: 14, fontWeight: bold, fontStyle: italic);
.news {
@include styleFont($val-map...);
}
.blog {
font: italic bold 12px/120% Arial, sans-serif;
}
.news {
font: italic bold 14px/120% Arial, sans-serif;
}
В данном примере мы добавляем через миксин значения для шрифта. В переменной $val, мы перечислили данные значения. При помощи переменных аргументов мы применили их при вызове миксина в блоке .blog. Сделали мы это так-же через оператор многоточия после переменной. Во втором примере мы передали карту значений $val-map, мы так же применили их через оператор многоточия. Какой вариант лучше применять, смотрите сами, можно и так, и так.
Возможна передача блока стилей в миксин. Давайте посмотрим как это делается.
@mixin keyframes ($name) {
@-webkit-keyframes #{$name} {
@content;
}
@-moz-keyframes #{$name} {
@content;
}
@-ms-keyframes #{$name} {
@content;
}
@keyframes #{$name} {
@content;
}
}
@include keyframes(balloon) {
50% {
top: 172px;
height: 77px;
margin-left: 235px;
}
70% {
top: 180px;
margin-left: -281px;
}
100% {
top: 22px;
height: 50px;
margin-left: -1072px;
}
}
@-webkit-keyframes balloon {
50% {
top: 172px;
height: 77px;
margin-left: 235px;
}
70% {
top: 180px;
margin-left: -281px;
}
100% {
top: 22px;
height: 50px;
margin-left: -1072px;
}
}
@-moz-keyframes balloon {
50% {
top: 172px;
height: 77px;
margin-left: 235px;
}
70% {
top: 180px;
margin-left: -281px;
}
100% {
top: 22px;
height: 50px;
margin-left: -1072px;
}
}
@-ms-keyframes balloon {
50% {
top: 172px;
height: 77px;
margin-left: 235px;
}
70% {
top: 180px;
margin-left: -281px;
}
100% {
top: 22px;
height: 50px;
margin-left: -1072px;
}
}
@keyframes balloon {
50% {
top: 172px;
height: 77px;
margin-left: 235px;
}
70% {
top: 180px;
margin-left: -281px;
}
100% {
top: 22px;
height: 50px;
margin-left: -1072px;
}
}
Пример выше - это старый вывод миксина для свойства keyframes. С 1 по 14 строчку мы определяем миксин, с 15 по 30 строчку мы его вызываем. Обратите внимание на директиву @content, благодаря ей все, что будет написано в миксине между фигурными скобками, будет подставлено на место данной директивы при компиляции CSS-файла.
В принципе мы освоили миксины. Не трудно догадаться, что они очень широко применялись, когда только-только появился CSS3. Сейчас autoprefix-ер позволяет значительно сократить их использование. Если вы во время работы видите, что у каких-либо блоков есть похожие стили, я рекомендую вынести их в миксины. Раньше моим самым часто используемым миксином был clearfix, сейчас я в миксин вынес пару стилей для выравнивания элементов на flex. Что выносить в миксины вы поймете со временем, как говорится больше практики.