Переменные в LESS
В этой статье вы узнаете, что такое переменные, как и для чего они используются в LESS, и в чем заключается преимущество в их использовании.
Переменная (variable) в LESS это поименованная область памяти, адрес (имя) которой можно использовать для осуществления доступа к заданному значению, и при необходимости изменять это значение в ходе объявления стилей. Другими словами это контейнер в который мы помещаем интересующее нас значение, и в любой момент мы можем воспользоваться этим значением, сославшись в нашем коде на этот контейнер (переменную).
Зачастую, одни и те же значения свойств могут повторяться десятки, а то и сотни раз в одной таблице стилей, препроцессор LESS поддерживает использование переменных, благодаря которым значительно упрощает монотонную работу. Переменные позволят Вам сделать код легче поддерживаемым, так как у вас появится возможность контролировать значения свойств из одного места, и при необходимости оперативно вносить необходимые правки.
Объявление переменной
Прежде чем использовать переменную в коде её необходимо объявить внутри файла less, или другими словами инициализировать. Имя переменной всегда должно начинаться со знака @. Если вы хорошо знакомы с CSS, то вы знаете, что в каскадных таблицах стилей знак @ указывает, что перед нами директива, или еще их называют правилами. Полный перечень директив (правил) вы можете найти в следующем разделе, не путайте их с переменными.
Синтаксис переменных всегда должен состоять из пар имя/значение:
@variableName: value; // имя и значение переменной
Давайте перейдем к рассмотрению простого примера объявления переменных в LESS и постепенно будем увеличивать сложность примеров по ходу статьи. Допустим нам необходимо разместить кнопку (элемент <button>), которая имеет одни цветовые стили для текста и границ элемента. Для этих целей создадим переменную:
@button-color: #b05049; // объявляем (инициализируем) переменную
После того как мы объявили переменную мы можем воспользоваться ей в своем коде, делается это следующим образом:
@button-color: #b05049; // объявляем (инициализируем) переменную button { color: @button-color; // используем переменную в качестве значения свойства border: 1px solid @button-color; // используем переменную в качестве части значения свойства }
Как вы можете догодаться после компиляции в CSS мы получим следующий результат:
button { color: #b05049; // цвет текста border: 1px solid #b05049; // стили для границ элемента }
В следующем примере мы создадим две переменные и укажем в качестве значения свойства переменную, которая содержит в себе имя другой переменной:
@me: "I am string"; @not-me: "me"; .selector { content: @@not-me; // @@not-me --> @me --> "I am string" }
В этом примере мы указали для CSS свойства content значение переменной, которое содержит в себе имя другой переменной. В ходе компиляции для начала будет найдено значение переменной @not-me, оно будет подставлено для поиска значения, получившейся переменной @me, которое и содержит финальный результат "I am string".
.selector { content: "I am string"; }
Хочу обратить Ваше внимание на то, что такая конструкция метаязыка LESS имеет право на жизнь, но встречается на практике очень редко, в основном для решения задач, которые можно решить и другим способом.
Давайте разберем пример, в котором объявим несколько переменных с одним именем уже после их использования в коде, и посмотрим, что мы получим при компиляции:
button { color: @button-color; // используем переменную в качестве значения свойства } @button-color: #b05049; // объявляем переменную @button-color: red; // объявляем одноименную переменную
В результате компиляции мы должны получить следующий результат:
button { color: red; // цвет текста }
Во-первых, необходимо понять из этого примера, что допускается использовать переменные до их инициализации (до того как они были объявлены). Во-вторых, переменные в LESS допускается переопределять, а это означает, что, если переменная ниже объявлена с тем же именем, то при компиляции будет использовано её значение. Но и здесь есть свои нюансы, связанные с областью видимости переменных, а что это такое мы узнаем в следующем разделе.
Область видимости переменных
В LESS, как и, например, в языках программирования JavaScript, PHP, или C# существует понятие области видимости переменных, она представляет из себя отдельный блок кода, в котором мы инициализируем переменную. Переменные в LESS бывают как глобальными, так и локальными. В этой статье мы уже с Вами сталкивались с объявлением глобальных переменных, например:
@section: #777; // объявляем глобальную переменную @section_inside: #999; // объявляем глобальную переменную div { background: @section; // используем переменную в качестве значения свойства > div { // селектор дочерних элементов (выбираем элементы <div>, вложенные в <div> background: @section_inside; // используем переменную в качестве значения свойства } }
Отличительной особенностью глобальных переменных служит то, что они не находятся внутри какого-то отдельного блока, а находятся в самом "верху", что делает доступным их из любого места в Вашем коде. Другими словами они имеют глобальную область видимости. В результате компиляции мы получим слуедующий результат:
div { background: #777777; // цвет заднего фона } div > div { background: #999999; // цвет заднего фона }
Второй тип переменных - локальные, они как вы уже догадались, размещаются внутри какого-либо блока и имеют свою локальную область видимости.
Давайте рассмотрим пример, в котором мы создадим одноименные переменные, которые имеют как локальную, так и глобальную область видимости:
@myVariable: violet; // объявляем глобальную переменную aside { @myVariable: yellow; // объявляем локальную переменную background: @myVariable // используем переменную в качестве значения свойства } @myVariable: red; // объявляем глобальную переменную
В связи с тем, что у нас имеется одноименная локальная переменная, то в результате компиляции будет использовано именно её значение, так как эта переменная является последней переменной, которая была объявлена в текущей области видимости (локальная область видимости).
Результат компиляции будет следующий:
aside { background: #ffff00; // желтый цвет в шестнадцатиричной системе }
К этому месту статьи вы уже должны прийти к пониманию того, что глобальные переменные доступны из любого места в коде, а вот локальные переменные, только из текущей области видимости. Например:
article { p { @myVariable: green; // объявляем локальную переменную color: @myVariable; // используем переменную в качестве значения свойства span { color: @myVariable; // используем переменную в качестве значения свойства } } }
Внутри вложенного селектора span доступно использование переменной, так как локальная область видимости распостроняется и на вложенные селекторы.
Обратите внимание на следующий пример в котором мы попытаемся воспользоваться локальной переменной, которая была инициализирована у вложенного элемента:
article { color: @myVariable; // переменная не доступна (undefined) - ошибка компиляции p { @myVariable: green; // объявляем локальную переменную color: @myVariable; // используем переменную в качестве значения свойства span { color: @myVariable; // используем переменную в качестве значения свойства } } }
Вышеприведенный код не будет скомпилирован по той причине, что инициализированная локальная переменная не будет доступна для использования внутри селектора span, так как она размещена не в текущей области видимости. Это очень важный момент, который необходимо понять при работе с локальными и глобальными переменными в LESS.
Обращаю Ваше внимание на то, что рекомендуется использовать переменные уже после их объявления, иначе, результат может быть не тем, который вы ожидаете. Рассмотрим следующий пример:
.selector { width: @my-var; @my-var2: 10%; } @my-var: @my-var2; @my-var2: 100%;
Это типичный пример, который мы разобрали выше, но его результат, возможно, Вас смутит:
.selector { width: 10%; }
В этом примере мы в качесте значения свойства width присваеваем переменную @my-var, компилятор находит эту переменную в глобальной области видимости, значение этой переменной соответствует имени переменной @my-var2. Теперь внимательно присмотритесь, у нас есть переменная @my-var2 как в локальной, так и глобальной области видимости. Компилятор выберет последнюю переменную, которая была объявлена в текущей области видимости, в нашем случае это локальная область видимости.
Ну и на последок пример, результат компиляции которого, я надеюсь, вы сможете определить самостоятельно:
@var: 0; // глобальная область видимости .class { @var: 1; // локальная область видимости property: @var; .nested-class { // вложенный класс @var: 2; // локальная область видимости property: @var; @var: 3; // локальная область видимости } }
Интерполяция переменных
Давайте с Вами разберем, что же такое интерполяция переменных в LESS, и в чем заключается её особенность. Интерполяция позволяет нам использовать произвольную строку, которая хранится в переменной в качестве строковых значений, или части строковых значений CSS правил, свойств, значений этих свойств, использовать это значение в наименовании селекторов и даже внутри селекторов.
В первую очередь рассмотрим пример интерполяции переменной внутри и вместо CSS свойств:
@myProperty: color; // инициализируем переменную body { @{myProperty}: #222; // интерполяция переменной в качестве свойства background-@{myProperty}: #333; // интерполяция переменной в качестве части свойства }
Обратите внимание на необходимость соблюдения определенного синтаксиса при проведении интерполяции, в котором необходимо помещать имя, интересующей нас переменной внутри конструкции:
@{} // имя переменной помещается между фигурных скобок
Результат компиляции нашего примера будет следующий:
body { color: #222; // цвет текста background-color: #333; // цвет заднего фона }
В следующем примере мы произведем интерполяцию переменной внутри значения CSS свойства:
@path: "/wwwroot/images/"; // инициализируем переменную body { background: url("@{path}main.png"); // интерполяцию переменной внутри значения header { background: url("@{path}header.png"); // интерполяцию переменной внутри значения nav { background: url("@{path}nav.png"); // интерполяцию переменной внутри значения } } }
В этом примере мы указали в качестве значения переменной строковый путь от корня сайта к файлам с изображениями, согласитесь это довольно удобно, так как нам достаточно определить интерполяцию переменной перед названием изображения. Даже если по каким-то причинам Вам необходимо будет физически переместить файлы с изображениями, то внесение изменений в стили займет минимум времени. Результат компиляции будет следующий:
body { background: url("/wwwroot/images/main.png"); // фоновое изображение для элемента } body header { background: url("/wwwroot/images/header.png"); // фоновое изображение для элемента } body header nav { background: url("/wwwroot/images/nav.png"); // фоновое изображение для элемента }
В заключении этого раздела рассмотрим пример в котором мы произведем интерполяцию переменной внутри селектора:
@my-selector: main-logo; // инициализируем переменную section .@{my-selector} { // интерполяцию переменной внутри селектора display: none; // элемент не будет отображаться }
По аналогии с предыдущими примерами для интерполяции переменной достаточно лишь поместить её внутри конструкции @{}. После компиляции в CSS мы получим следующий результат:
section .main-logo { display: none; // элемент не будет отображаться }
Экранирование в LESS
В этом разделе мы рассмотрим такую возможность LESS как экранирование символов. В настоящее время эта особенность метаязыка устарела и не так часто используется, но встречается при решении некоторых специфических задач. Для чего может использоваться экранирование? Например, если Вам необходимо использовать произвольную строку в качестве CSS свойства, или его значения, а по мнению компилятора Ваш код считается не валидным (не стандартным), то необходимо поместить его в одну из следующих конструкций:
~"value" // синтаксис с двойной кавычкой ~'value' // синтаксис с одинарной кавычкой
Не будем тратить время и сразу перейдем к примеру:
@myVariable: myValue; // инициализируем переменную body:before { filter: ~"ms:special.browser.syntax()"; // код будет скомпилирован только с экранированием (указано не стандартное значение) content: ~"@{myVariable}"; // интерполяция внутри экранирования }
В этом примере мы применили экранирование к значениям CSS свойств, в первом свойстве оно позволило скомпилировать код для использования не стандартного значения, а во втором лишь для демонстрации работы интерполяции внутри экранирования.
Главное правило экранирования, которое необходимо понять: все, что Вы поместите внутри ~"" будет скомпилировано без изменений, за исключением использования интерполяции внутри конструкции экранирования.
Результат компиляции:
body:before { filter: ms:special.browser.syntax(); // не стандартное значение свойства content: myValue; // строковое содержимое свойства }
Свойства как переменные
С выходом LESS версии 3.0 стало доступно использование такого синтаксиса, при котором имена объявленных свойств могут использоваться в качестве пременной, для этого достаточно вызвать интересующее Вас свойство со следующим синтаксисом:
.myClass { color: #fff; background: $color; // используем имя свойства как переменную }
Если вы используете LESS версии 3.0 или старше, то результат компиляции должен быть следующий:
.myClass { color: #fff; background: #fff; }
Давайте рассмотрим следующий пример, в котором используем свойство в качестве переменной для вложенного селектора:
.parent { color: #fff; .nested { background: $color; // используем имя свойства как переменную } color: #000; }
Обратите внимание, что, как и при работе с обычными переменными компилятор LESS выберет последнее свойство в текущей, или родительской области видимости в качестве значения, которое будет установлено.
Если вы используете LESS версии 3.0 или старше, то результат компиляции должен быть следующий:
.parent { color: #fff; color: #000; } .parent .nested { background: #000; }