Перейти к содержанию

Использование переменных

В любом полноценном языке программирования есть переменные (от англ. variables), которые представляют собой именованную область памяти и позволяют записывать в себя какие-либо данные. Переменные дают возможность обращаться к себе по имени, а также изменять присвоенные им значения.

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

Процесс объявления (определения) переменных и присваивания им значения называют инициализацией.

Обычно, переменные переопределяемые, то есть при инициализации в них можно записать значение и, по ходу работы программы, изменять его столько раз, сколько нужно разработчику. К сожалению, существуют переменные с неизменяемыми значениями — непереопределяемые.

В Less переменные динамические, переопределяемые и требующие инициализации.

Любая переменная в Less инициализируется как директива, то есть с использованием символа собачки (@) в начале.

@block-background: #f5f5f5;
@block-color: #333;
@block-border-color: #ddd;

Для того, чтобы использовать значение переменной при написании кода, необходимо её вызвать. Делается это так:

.block {
  background-color: @block-background;
  color: @block-color;
  border: 1px solid @block-border-color;
}

Хранение данных

В переменных можно хранить любые данные, которые подходят под шаблон @name: value;. Для примера я подобрал несколько значений, которые можно присвоить переменным:

@var-color: #ffff00;
@var-string-0: header;
@var-string-1: 0 auto;
@var-number: 4768;
@var-value: 14px;
@var-rule: {
  color: red;
};
@var-url-0: '../images/nichosi-meme.png';
@var-url-1: url('../images/nichosi-meme.png');

Операции с переменными (операторы)

Оператором называется нечто, принимающее одно или более значений (или выражений, если говорить на жаргоне программирования), и вычисляющее новое значение (таким образом, вся конструкция может рассматриваться как выражение).

В Less присутствует два режима интерпретации операций с выражениями: обычный и строгий.

Арифметические операции (обычный режим)

Допускается производить операции с выражениями, значения которых соответствуют строкам.

Пример Название Результат Числа Строки
[email protected] Отрицание Смена знака @a + ошибка
@a + @b Сложение Сумма @a и @b + игнорируется*
@a - @b Вычитание Разность @a и @b + игнорируется*
@a * @b Умножение Произведение @a и @b + игнорируется*
@a / @b Деление Частное от деления @a на @b + игнорируется*

* — игнорируется при условии, что производится операция с явно указанной строкой в выражении не через переменную, а напрямую. Иначе ошибка.

Арифметические операции (строгий режим)

Для включения строгого режима арифметических операций нужно взять выражения в круглые скобки (выражение). В таком режиме запрещается производить операции со строками.

Пример Название Результат Числа Строки
([email protected]) Отрицание Смена знака @a + ошибка
(@a + @b) Сложение Сумма @a и @b + ошибка
(@a - @b) Вычитание Разность @a и @b + ошибка
(@a * @b) Умножение Произведение @a и @b + ошибка
(@a / @b) Деление Частное от деления @a на @b + ошибка

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

@a @b @a + @b @a - @b @a * @b @a / @b
1 1 2 0 1 1
1px 2 3px -1px 2px 0.5px
5% 4 9% 1% 20% 1.25%
2% 3px 5% -1% 6% 0.6666..66%
0.33 11% 11.33% -10.67% 3.6300...03% 0.0300...02%
#6699cc 25% #6b9ed1 #6194c7 #ffffff #141f29
#666 #333 #999999 #333 #ffffff #020202

Экранирование

Экранирование — это замена управляющих символов на соответствующие текстовые подстановки. Делается это для того, чтобы использовать некоторые строковые конструкции в рамках языка, которые компилятор может принять за конструкции самого языка.

В Less такой опасной конструкцией могут стать фильтры, которые для IE часто принимают вид:

.element {
  filter: ms:alwaysHasItsOwnSyntax.For.Stuff();
}

Если попытаться скомпилировать этот блок кода, компилятор будет нарываться на ошибку и любезно сообщать её нам:

$ lessc _styles.less > styles.css

ParseError: Unrecognised input in _styles.less on li ne 24, column 13:

23 .element {
24   filter: ms:alwaysHasItsOwnSyntax.For.Stuff();
25 }

Разумеется, ничего хорошего из этого не выйдет, но решение этой проблемы, как гласит название раздела — экранирование.

Экранирование в Less может осуществляться двумя способами. Первый путь подразумевает под собой использование функции e(), а второй — синтаксической конструкции ~"" или ~''. Оба способа ожидают на входе строку, окружённую кавычками, которые при компиляции будут удалены.

.element {
  filter: e('ms:alwaysHasItsOwnSyntax.For.Stuff()');
  filter: ~'ms:alwaysHasItsOwnSyntax.For.Stuff()';
  filter: ~'ms:alwaysHasItsOwnSyntax.For.Stuff()';
}

Экранирование с помощью функции e() считается устаревшим. Создатели Less предлагают повсеместно внедрять синтаксическую конструкцию ~"" или её аналог с одинарными кавычками.

Области видимости

Практически во всех языках программирования есть базовые области видимости (от англ. scope), представляющие собой область программы, в которой доступно значение объявленной переменной. Если переменная объявлена внутри функции, то её область видимости ограничивается этой функцией, а сама переменная называется локальной. Если же переменная объявлена вне функции, то она — глобальная.

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

Причём Less никак не противится глобальных переменных, наоборот, будет лучше, если все объявленные переменные будут глобальными. Я имею в виду то, что в JavaScript, например, создание лишних глобальных переменных считается роскошью и наказывается. В Less же картина резко противоположная и на то есть весомые причины.

Обычно, в Less переменные хранятся в большом файле с названием _variables.less, и вызвано это тем, что так действительно удобнее организовывать хранение, изменение и поддержку актуальности данных. При необходимости разработчик может использовать глобальные переменные где угодно, то есть в любом файле или селекторе. При этом не требуется искать переменные по всем файлам проекта. Разумеется, что речь идёт про редакторы, у которых нет автодополнения переменных.

Свою область видимости в Less создают селекторы, ссылки на родителя селектора (&) и примеси.

Пример 3.1.1

Рассмотрим пример, демонстрирующий работу переменных и области видимости в Less.

Создадим файл _styles.less и добавим туда несколько глобальных переменных и селекторов.

// Variables
@body-background: #f5f5f5;
@body-font-size: 14px;

// Code
body {
  background-color: @body-background;
  font-size: @body-font-size;
}

.block {
  @block-color: #333;
  @block-font-size: 28px;

  font-size: @block-font-size;
  color: @block-color;
}

.element {
  font-size: @block-font-size;
}

При компиляции возникнет ошибка из-за того, что переменная @block-font-size локальная и не может быть использована вне селектора .block. При этом глобальные переменные никаких ошибок породить не могут, так как они доступны во всем коде.

$ lessc _styles.less > styles.css

NameError: variable @block-font-size is undefined in _styles.less on line 20, column 14:

19 .element {
20   font-size: @block-font-size;
21 }

Ленивая загрузка

Переменные в Less настолько ленивые, что их можно объявлять до их непосредственного применения (вызова) и после него. В теории это значит, что переменная инициализируется в точке её вызова, а это значит, что вы можете использовать переменные до того, как вы их объявите.

.lazy {
  width: @lazy-width;
}

@lazy-width: @lazy-height;
@lazy-height: 200px;

После компиляции получится следующий код:

.lazy {
  width: 200px;
}

Но при таком использовании нужно помнить, что локальные переменные превосходят по важности глобальные. Это правило описано ранее в части «Области видимости». То есть, если использовать две одинаковые по имени переменные, но одна из них будет локальной, а другая глобальной, то все будет зависеть от их места определения и использования.

В этом случае переменная @lazy-height будет локальной для объявления селектора .lazy и именно её значение будет использоваться при подстановке в @lazy-width.

.lazy {
  width: @lazy-width;
  @lazy-height: 100px;
}

@lazy-width: @lazy-height;
@lazy-height: 200px;

После компиляции свойству width будет присвоено значение 100px:

.lazy {
  width: 100px;
}

Кроме того, в Less, как и в CSS, роль играет последовательность объявления переменных. Имеется в виду, что будет использоваться та переменная, которая объявлена ниже всех.

@element-height: 100px; // 1

.element {
  @element-height: 200px; // 2
  height: @element-height;

  &-footer {
    height: @element-height;
    @element-height: 300px; // 3
    height: @element-height;
    @element-height: 400px; // 4
  }

  @element-height: 500px; // 5
}

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

  • Объявление (1) сразу же можно забыть, так как оно глобальное, а внутри селектора .element находятся локальные переменные.
  • Локальные объявления (2, 3) тоже можно не учитывать, так как ниже происходит инициализация других переменных.
  • Локальное объявление (4) будет использовано внутри объявления .element-footer, которое формируется с использованием родительского селектора.
  • Локальное объявление (5) будет использовано внутри селектора .element.
.element {
  height: 500px;
}
.element-footer {
  height: 400px;
}

Не стоит запоминать или заучивать все происходящее в этой части главы, просто будьте уверены, если переменная объявлена ниже всех, то применяться будет именно она. Разумеется, что в рамках её локальности или глобальности.

Переменные по умолчанию

На основании «ленивой загрузки» в Less предоставляется возможность организации переменных по умолчанию. Возможно, это не такой удобный и явный способ, который предлагает Sass, но, тем не менее, такое практикуется, нужно знать и использовать во благо своих целей.

Ниже приведён код, в котором переопределяется переменная @color-green. Получается, что в файле библиотеки вместо глобальной переменной, объявленной внутри неё, будет использована переданная переменная @color-green со значением #003300.

// Переменные в файле _library.less
@color-green: green;
@color-red: red;

// Импорт библиотеки и переопределенная переменная
@import '_library';
@color-green: #003300;

Такое поведение может пригодиться при использовании библиотек или фреймворков, в которых разработчику необходимо переопределить переменные. Но вы должны понимать, что на самом деле значения переменных не изменяются, а происходит та самая «ленивая загрузка».

Переопределение переменных делает настройку структур, таких как Bootstrap 3, более гибкой и простой. Но об этом я расскажу вам в соответствующей главе.