Статьи

Понимание переменной области в Sass

В этой статье мы более подробно рассмотрим переменные и область видимости переменных в Sass. Область действия переменной описывает контекст, в котором она определена, и, следовательно, где она доступна для использования.

Для начала я расскажу, какие области поддерживает Sass. Затем я объясню два полезных флага, которые мы можем использовать для настройки значения переменной. Наконец, я кратко представлю доступные функции для проверки, существует ли переменная или нет.

Sass поддерживает два типа переменных: локальные и глобальные переменные.

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

1
$bg-color: green;

С другой стороны, локальные переменные — это те, которые объявлены внутри селектора. Позже мы рассмотрим, как мы можем настроить это поведение. Но пока давайте посмотрим на наш первый пример.

Здесь мы определяем mixin, а затем btn-bg-color внутри него. Это локальная переменная, и поэтому она видна только коду внутри этого миксина:

1
2
3
4
@mixin button-style {
    $btn-bg-color: lightblue;
    color: $btn-bg-color;
}

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

1
2
3
button {
    @include button-style;
}

Полученный CSS:

1
2
3
button {
    color: lightblue;
}

Представьте, однако, что мы также хотим использовать эту переменную (не mixin) в другом селекторе:

1
2
3
.wrap {
    background: $btn-bg-color;
}

Это даст нам следующую ошибку:

1
Undefined variable: «$btn-bg-color».

Этого следовало ожидать, верно? Мы попытались получить доступ к переменной mixin, которая имеет локальную область видимости. Не волнуйтесь, как уже упоминалось выше, мы исправим эту проблему в следующем разделе.

Стоит также отметить, что если мы объявим переменную внутри селектора, любой другой вложенный селектор сможет получить к ней доступ. Вот пример:

1
2
3
4
5
6
7
.wrap {
    $bg-color: red;
     
    &:after {
        background: lighten($bg-color, 10%);
    }
}

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

1
2
3
.wrap:after {
    background: #ff3333;
}

Однако, посмотрите на пример ниже, где мы определяем функцию, затем используем эту функцию вместе с вложенным селектором:

01
02
03
04
05
06
07
08
09
10
11
12
@function my-function() {
    $text-color: black;
    @return $text-color;
}
     
.wrap {
    color: my-function();
     
    &:after{
        background: $text-color;
    }
}

Если мы попытаемся скомпилировать это, мы получим ту же ошибку, о которой говорилось ранее. Опять же, это происходит потому, что мы не можем получить доступ к переменной text-color . Он не определен непосредственно в родительском селекторе, а внутри функции, которую вызывает наш селектор.

Глобальные и локальные переменные могут иметь одинаковые имена. Чтобы продемонстрировать такое поведение, мы будем работать над четвертым примером:

01
02
03
04
05
06
07
08
09
10
11
$text-color: tomato;
 
@mixin button-style {
    $text-color: lime;
    color: $text-color;
}
     
@mixin link-style {
    $text-color: black;
    color: $text-color;
}

Здесь мы определили три разные переменные ( text-color ) с одинаковым именем. Первая из них является глобальной переменной, а две другие являются локальными.

Вот некоторые стили, использующие их:

01
02
03
04
05
06
07
08
09
10
11
button {
    @include button-style;
}
      
a {
    @include link-style;
}
      
.wrap {
    background: $text-color;
}

И сгенерированный CSS:

01
02
03
04
05
06
07
08
09
10
11
button {
    color: lime;
}
     
a {
    color: black;
}
     
.wrap {
    background: tomato;
}

Это то, что вы ожидали?

Имейте в виду, что мы не увидим эти стили, если мы не скомпилируем текущую версию Sass (3.4). Например, предположим, что мы используем Sass 3.3, наш вывод CSS будет выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
button {
    color: lime;
}
     
a {
    color: black;
}
     
.wrap {
    background: black;
}

Обратите внимание на разницу в цвете фона селектора .wrap . Это происходит потому, что в соответствии с более ранними версиями Sass (то же самое для LibSass), если мы локально переопределим значение глобальной переменной (например, text-color ), это будет новое (глобальное) значение переменной. Итак, в нашем примере скомпилированные стили зависят от порядка, в котором мы объявляем переменную и mixins.

Этот флаг позволяет нам установить значение переменной, если она еще не установлена ​​или ее текущее значение равно null (рассматривается как неназначенное). Чтобы лучше объяснить, как мы можем воспользоваться этим в реальном сценарии, давайте предположим, что у нас есть проект со следующей структурой:

1
2
3
4
5
6
7
8
9
Project-Name/
   ├── …
   ├── css/
   │ └── app.css
   └── scss/
       ├── _config.scss
       ├── _variables.scss
       ├── _mixins.scss
       └── app.scss

Файл app.scss выглядит так:

1
2
3
4
5
6
7
8
9
@import «config»;
@import «variables»;
@import «mixins»;
     
button {
    @include button-style;
}
 
// more styles

Давайте посмотрим содержимое частичных файлов.

Во-первых, файл variables.scss содержит наши переменные:

1
2
3
4
$btn-bg-color: lightblue !default;
$btn-bg-color-hover: darken($btn-bg-color, 5%);
     
// more variables

Обратите внимание на флаг по default назначенный btn-bg-color .

Во-вторых, файл mixins.scss включает в себя наши миксины:

01
02
03
04
05
06
07
08
09
10
11
@mixin button-style ($bg-color: $btn-bg-color, $bg-color-hover: $btn-bg-color-hover) {
    background-color: $bg-color;
    // more styles
         
    &:hover {
        background-color: $bg-color-hover;
        // more styles
    }
}
     
// more mixins

Тогда сгенерированный файл app.css будет выглядеть следующим образом:

1
2
3
4
5
6
7
button {
    color: lightblue;
}
     
button:hover {
    background-color: #99cfe0;
}

Итак, наши кнопки поставляются со стилями по умолчанию. Но давайте предположим, что мы хотим иметь возможность перезаписать их, применяя наши пользовательские значения. Для этого мы можем переназначить нужные переменные (по умолчанию) в частичном файле config.scss :

1
2
3
$btn-bg-color: chocolate;
     
// more variables

Установка значения этой переменной в chocolate приведет к игнорированию соответствующего значения ( lightblue ), получившего флаг по default . Следовательно, сгенерированный CSS изменяется, как мы видим ниже:

1
2
3
4
5
6
7
button {
    color: chocolate;
}
     
button:hover {
    background-color: #bc5e1b;
}

Примечание : в случае, если мы не добавили флаг по default в btn-bg-color , наш CSS из-за каскадной природы CSS будет выглядеть следующим образом:

1
2
3
4
5
button {
    color: lightblue;
}
     
// hover styles

Этот второй флаг помогает нам изменить область действия локальной переменной.

Вы помните ошибку, которую мы видели в нашем первом примере? Это произошло потому, что мы попытались использовать btn-bg-color в селекторе .wrap . Давайте изменим наш пример, чтобы включить этот новый флаг. Вот новые стили:

01
02
03
04
05
06
07
08
09
10
11
12
@mixin button-style {
    $btn-bg-color: lightblue !global;
    color: $btn-bg-color;
}
     
button {
    @include button-style;
}
     
.wrap {
    background: $btn-bg-color;
}

Как вы можете видеть ниже, благодаря этому флагу CSS компилируется без ошибок:

1
2
3
4
5
6
7
button {
    color: lightblue;
}
     
.wrap {
    background: lightblue;
}

global флаг полезен, но имейте в виду, что не всегда хорошая практика изменять область видимости переменной.

Sass предоставляет две функции самоанализа для проверки, существует ли переменная или нет. Мы можем использовать функции variable-exists и / или global-variable-exists чтобы проверить, существуют ли наши локальные и / или глобальные переменные соответственно.

Например, вот пример общего использования, где мы определяем переменную, содержащую абсолютный путь к шрифту Google . Затем мы выбираем импорт этого шрифта в наши таблицы стилей, но только если была создана соответствующая переменная.

1
2
3
4
5
$google-font: «http://fonts.googleapis.com/css?family=Alegreya»;
     
@if(global-variable-exists(google-font)) {
    @import url($google-font);
}

Результат:

1
@import url(«http://fonts.googleapis.com/css?family=Alegreya»);

В этой статье я познакомил вас с концепцией переменной области видимости в Sass. Чтобы прояснить ситуацию, мы рассмотрели различные примеры, поэтому, надеюсь, у вас теперь есть хорошее понимание того, как работает сфера. Вы можете найти все примеры этой статьи в этой сути SassMeister и не стесняйтесь задавать любые вопросы, которые могут у вас возникнуть в комментариях!