Основы Sass: Управляющие директивы и выражения
HTML&CSS

Основы Sass: Управляющие директивы и выражения

Оригинал: Sass Basics: Control Directives and Expressions, Reggie Dawson

Если вы посмотрите исходные коды такого фреймворка, как Foundation, вы заметите, что миксины используют управляющие директивы, такие как @if и @for, для создания классов сетки.

Продолжая осваивать основы Sass, мы обсудим эти управляющие директивы и рассмотрим, как использовать их в своих проектах. Они могут вам не понадобиться, но всегда хорошо знать, какие инструменты находятся в вашем распоряжении. if()

Это не управляющая директива, а встроенная функция Sass. Это не то же самое, что и директива @if(), функция if() позволяет проверить условное выражение и возвращает одно из двух возможных значений. Выражение может быть либо истинно, либо ложно. Например:


@mixin test($condition) {
    $color: if($condition, blue, red);
    color:$color
}

.firstClass {
    @include test(true);
}

.secondClass {
    @include test(false);
}

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


.firstClass {
    color: blue;
}

.secondClass {
    color: red;
}

Аргументами функции if() являются выражение, которое должно быть проверено, результат, который вернется, если выражение истинно, и результат, который вернется, если выражение ложно. Любое значение, кроме false или null, считается истинным. В примере выше вместо true можно передать число, результат будет тот же.


.firstClass {
    @include test(1);
}

@if

Директива @if принимает выражение и возвращает стили, если выражение истинно. Например:


@mixin txt($weight) {
    color: white;
    @if $weight == bold { font-weight: bold;}
}

.txt1 {
    @include txt(none);
}

.txt2 {
    @include txt(bold);
}

Получим:


.txt1 {
    color: white;
}

.txt2 {
    color: white;
    font-weight: bold;
}

К директиве @if может быть добавлено несколько директив @else if и завершающая директива @else. Таким образом можно проверить несколько выражений. Расширим предыдущий пример:


@mixin txt($weight) {
    color: white;
    @if $weight == bold { font-weight: bold;}
    @else if $weight == light { font-weight: 100;}
    @else if $weight == heavy { font-weight: 900;}
    @else { font-weight: normal;}
    }

.txt1 {
    @include txt(bold);
}

.txt2 {
    @include txt(light);
}

.txt3 {
    @include txt(heavy);
}

.txt4 {
 @include txt(none);
}

.txt5 {
    @include txt(normal)
}

Результат:


.txt1 {
    color: white;
    font-weight: bold;
}

.txt2 {
    color: white;
    font-weight: 100;
}

.txt3 {
    color: white;
    font-weight: 900;
}

.txt4 {
    color: white;
    font-weight: normal;
}

.txt5 {
    color: white;
    font-weight: normal;
}

Я добавил два последних класса, чтобы показать, как работает директива @else, когда ни одно из условий не выполняется. В первом примере, если в качестве аргумента не передается bold, никакие стили не добавляются. Если мы добавляем @else, и ни одно из условий для @if и @else if не срабатывает, добавляются стили для @else. Вот почему классы .txt4 и .txt5 имеются значение font-weight.

@for

Директива @for позволяет добавить стили в цикле. Директива может работать как от начального значения до конечного, так и наоборот. Разница лишь в том, что в прямом порядке конечное значение не включено, а в обратном — включено. Директива @for использует переменную для проверки диапазона. Для того, чтобы счетчик итераций работал в обратном порядке, необходимо начальное значение задать больше конечного. Рассмотрим пример:


@for $i from 1 through 12 {
    .col-#{$i} { width: 100/12 * $i;}
}

В этом примере мы с помощью @for создаем стили для колонок. После @for указывается переменная, в данном случае $i. Затем следует начальное значение переменной (1) и конечное (12). На каждой итерации цикл генерирует стили. Обратите внимание, как мы используем интеполяцию, подставляя значение переменной $i в название класса.


.col-1 {
    width: 8.33333;
}

.col-2 {
    width: 16.66667;
}

.col-3 {
    width: 25;
}

.col-4 {
    width: 33.33333;
}

Я не привел все сгенерированные стили, они продолжаются до 12. При каждом проходе цикла создается класс, значение переменной подставляется в название класса. Также на основе значения переменной вычисляется ширина колонки.

@each

Директива @each использует список элементов вместо начального и конечного значений. При каждом проходе цикла переменная принимает значение одного из элементов этого списка.


@each $usr in bob, john, bill, mike {
    .#{$usr}-avatar {
        background-image: url('/img/#{$usr}.png');
    }
}

После @each указывается переменная, в нашем случае $usr. Далее идет список элементов, здесь также может использоваться map. И наконец, мы используем интерполяцию для формирования имени класса и пути к изображению.


.bob-avatar {
    background-image: url("/img/bob.png");
}

.john-avatar {
    background-image: url("/img/john.png");
}

.bill-avatar {
    background-image: url("/img/bill.png");
}

.mike-avatar {
    background-image: url("/img/mike.png");
}

Если используется map, необходимо присвоить значение двум переменным. Например:


$ppl: ( usr1:bob, usr2:john, usr3:bill, usr4:mike );

@each $key, $usr in $ppl  {
    .#{$usr}-avatar {
        background-image: url('/img/#{$usr}.png');
    }
}

В примере мы добавили вторую переменную для хранения ключа каждого значения. Если бы мы этого не сделали, в сгенерированных стилях вместо значения были бы подставлены ключи. Также можно использовать множественные присваивания.


$alt: alert, yellow, red;

$sub: submit, white, green;

$bck: back, blue, transparent;

@each $type, $txt, $back in $alt,$sub,$bck {
    .#{$type}-button {
        color: $txt;
        background-color: $back;
    }
}

В примере выше для создания классов мы используем несколько списков. При каждом проходе цикла элементы из этих списков присваиватся переменным. Результат:


.alert-button {
    color: yellow;
    background-color: red;
}

.submit-button {
    color: white;
    background-color: green;
}

.back-button {
    color: blue;
    background-color: transparent;
}

@while

Директива @while генерирует стили, пока переданное ей условие не станет равно false. Она похожа на директиву @for, но дает большую гибкость. Я могу переписать пример с @for так, чтобы он использовал директиву @while.


$x:1;

@while $x < 13 {
    .col-#{$x} { width: 100/12 * $x;}
    $x: $x + 1;
};

Вместо того, чтобы задать диапазон значений, как в примере с @for, мы меняем значение переменной в цикле и снова проверяем условие. В примере выше пока переменная $x меньше 13, выводим стили. Как только значение переменной дойдет до 13, условие не выполнится и цикл остановится. Ключевая вещь, которую нужно помнить — обязательно нужно изменять значение переменной, иначе цикл никогда не завершится.

Заключение

Sass имеет множество мощных особенностей, упрощающих фронтенд-разработку. И хотя управляющие директивы действительно являются очень мощными, в небольшом проекте не часто можно найти им применение. Главное — знать инструменты, которые есть в нашем распоряжении. Возможно когда-нибудь они пригодятся.

Рассылка
Подпишитесь на рассылку и получайте дайджест новостей и статей.
Никакого спама!
Подписаться