В этой статье мы более подробно рассмотрим переменные и область видимости переменных в Sass. Область действия переменной описывает контекст, в котором она определена, и, следовательно, где она доступна для использования.
Для начала я расскажу, какие области поддерживает Sass. Затем я объясню два полезных флага, которые мы можем использовать для настройки значения переменной. Наконец, я кратко представлю доступные функции для проверки, существует ли переменная или нет.
Sass Variable Scope
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.
Флаг по default
Этот флаг позволяет нам установить значение переменной, если она еще не установлена или ее текущее значение равно 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
|
global
флаг
Этот второй флаг помогает нам изменить область действия локальной переменной.
Вы помните ошибку, которую мы видели в нашем первом примере? Это произошло потому, что мы попытались использовать 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 и не стесняйтесь задавать любые вопросы, которые могут у вас возникнуть в комментариях!