Использование примесей
Когда-то давно, наверное, только ленивый разработчик не мечтал о переиспользуемом CSS-коде. Вы только представьте себе то, что какой-нибудь блок кода может быть вызван повторно, и все его свойства станут доступны и второму селектору. Тогда это были желания, сейчас же это реальность.
В отличие от других CSS-препроцессоров, в Less любой объявленный селектор может использоваться как примесь. Примесь (от англ. mix-in) — набор свойств и селекторов, расширяющий поведение другой сущности (селектора).
Рассмотрим типичное объявление, которое уже миллионы раз встречалось в вашем CSS-коде:
.bordered {
border-top: dotted 1px #333;
border-bottom: solid 2px #333;
}
Казалось бы, ничего необычного, но ровно до тех пор, пока не сделать следующее:
.article {
.bordered;
color: #443d3d;
}
После компиляции селектор .bordered
безвозмездно отдаст все свои свойства и вложенные правила селектору .article
. При этом в конечном CSS-файле будут объявлены оба этих селектора.
.bordered {
border-top: dotted 1px #333;
border-bottom: solid 2px #333;
}
.article {
border-top: dotted 1px #333;
border-bottom: solid 2px #333;
color: #443d3d;
}
На самом деле, такая запись практически не используется на практике и не называется примесью. Настоящая примесь — она какая-то другая, волшебная. Но различие в них настолько мало, что и заметить бывает сложно:
.bordered() {
border-top: dotted 1px #333;
border-bottom: solid 2px #333;
}
.article {
.bordered;
color: #443d3d;
}
В этой записи я добавил скобки после селектора .bordered
, и уже сейчас он может гордо носить название примеси. В этом случае при компиляции не будет создан класс .bordered
, так как у него указаны скобки после имени. Такая конструкция говорит компилятору, что она чистейшая примесь, которая не хочет быть скомпилирована без явных на то причин.
.article {
border-top: dotted 1px #333;
border-bottom: solid 2px #333;
color: #443d3d;
}
Неважно, будут ли указаны скобки при вызове примеси (.bordered();
) или нет (.bordered;
) — результат будет одинаковым. Однако, я бы советовал их указывать из-за того, что примеси могут иметь параметры.
Примеси с параметрами
Для того, чтобы примеси были переиспользуемыми в различных контекстах, у них могут быть указаны параметры, в зависимости от которых может меняться цвет, фон и другие значения. Параметры указываются в скобках после имени примеси и представляют собой обычные локальные переменные.
.bordered(@_color) {
border-top: dotted 1px @_color;
border-bottom: solid 2px @_color;
}
.article {
.bordered(#ccc);
color: #443d3d;
}
Такая конструкция напоминает функции в JavaScript или других языках программирования, но на деле ей не является, так как работает скорее как макрос.
.article {
border-top: dotted 1px #cccccc;
border-bottom: solid 2px #cccccc;
color: #443d3d;
}
Параметров может быть неограниченное число, главное — чтобы они помещались на вашем экране и были читаемы.
Разделять параметры при объявлении примеси и её вызове можно запятыми (@a, @b)
, либо точкой с запятой (@a; @b)
.
Пример 3.4.1
В этом примере отображена возможность работы с вложенными селекторами внутри примеси.
.clearfix() {
&:before,
&:after {
display: table;
content: "";
}
&:after {
clear: both;
}
}
.navbar {
.clearfix();
}
Ничего необычного, получен вполне ожидаемый результат:
.navbar:before,
.navbar:after {
display: table;
content: "";
}
.navbar:after {
clear: both;
}
Замечу ещё раз, что из-за указанных скобок у селектора .clearfix
, соответствующий класс не будет объявлен после компиляции.
Значения параметров по умолчанию
Важной отличительной чертой примесей является возможность указывать значения по умолчанию для переменных. То есть в случае, если примесь вызвана, а значения для параметров не были переданы или переданы частично, то ошибки компилятор не выдаст, а возьмёт значение, указанное по умолчанию.
.bordered(@_color: #ccc) {
border-top: dotted 1px @_color;
border-bottom: solid 2px @_color;
}
.article {
.bordered();
color: #443d3d;
}
Эта запись не имела бы смысла, но так как указано значение по умолчанию, то при компиляции будет подставлено именно оно:
.article {
border-top: dotted 1px #cccccc;
border-bottom: solid 2px #cccccc;
color: #443d3d;
}
Все было бы хорошо, если бы для всех параметров указывались значения по умолчанию и их не нужно было изменять в зависимости от контекста применения примеси. На практике редко встречаются примеси, у которых используются указанные по умолчанию значения.
Рассмотрим пару примеров, которые показывают различные ситуации, часто встречающиеся на практике в реальных проектах.
Пример 3.4.2
Иногда необходимо изменить не все параметры, а лишь некоторые из них. Делается это следующим образом:
.transition(@function: ease, @duration: .3s, @property: all) {
transition-timing-function: @function;
transition-duration: @duration;
transition-property: @property;
}
.link {
.transition(@duration: 1s);
}
Вместо того, чтобы писать все три значения для переменных, я указал конкретную переменную и обновил её значение. Компилятор возьмёт значения по умолчанию для переменных @function
и @property
, а значение переменной @duration
будет взято из объявления вызова примеси.
.link {
transition-timing-function: ease;
transition-duration: 1s;
transition-property: all;
}
Пример 3.4.3
Если нужно изменить переменные, указанные слева, то писать переменные не нужно. Просто передайте при вызове необходимое количество значений.
.transition(@function: ease, @duration: .3s, @property: all) {
transition-timing-function: @function;
transition-duration: @duration;
transition-property: @property;
}
.block {
.transition(linear);
}
.link {
.transition(linear, .5s);
}
После компиляции получится следующая картина:
.block {
transition-timing-function: linear;
transition-duration: 0.3s;
transition-property: all;
}
.link {
transition-timing-function: linear;
transition-duration: 0.5s;
transition-property: all;
}
Пример 3.4.4
Внутри примеси можно творить все что угодно с переданными переменными и теми, что были указаны глобально. Этот пример я не могу продемонстрировать на реальном коде, так как стараюсь избегать взаимодействия глобальных и локальных переменных внутри примеси.
@global: 3;
.calc(@a: 1, @b: 2, @c: @global) {
@d: @a + @b + @c;
content: @d;
}
.test {
.calc();
}
Судя по правилам математики должно получиться 6.
.test {
content: 6;
}
Мысли и советы
Используйте значения параметров по умолчанию, если это может сократить вызов примеси. Однако, при этом не должен потеряется смысл вызова, то есть разработчику должно быть понятно, что и как делает эта примесь.