Имитация именованных переменных в LESS (с примером в jsFiddle)

Объяснять, что такое LESS, я не буду. Но таки пару слов скажу.

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

Проблема

При объявлении миксина, принимающего параметры, обязательно должны указываться значения параметров по-умолчанию. Это позволяет, при желании, вызывать миксин без передачи всех или части параметров. Но миксин в LESS пока не поддерживает именованные параметры. То есть, если миксин объявлен с 10 параметрами и необходимо изменить значение только десятого по порядку, придется передавать и предыдущие девять тоже. Да, со значениями по-умолчанию.


Исходные условия


Разметка

<div class="base-1">
    Это "BASE-1"
</div>

<div class="extension">
    Это "EXTENSION"
</div>

<div class="base-2">
    Это "BASE-2"
</div>


Стили LESS

/* объявляем миксин с параметрами по-умолчанию */
.f-border (
        @width: 4px, 
        @style: solid,
        @color: #BE2
    ) {
    border: @width @style @color;
}

/* вызываем миксин без параметров */
.base-1 {
    .f-border;
}

/* вызываем миксин c параметрами */
/* при этом изменяется только третий */
.extension {
    .f-border(4px, solid, #F16);
}

/* вызываем миксин без параметров */
.base-2 {
    .f-border;
}


Результат


Исходный код в jsFiddle.net***.

Проблема

В классе .extension в миксин передается вместо одного изменяемого параметра целых три, два из которых совпадают со значениями по-умолчанию. В данном конкретном случае это не является проблемой, так как параметров достаточно мало. Но, к примеру, в моем проекте, связанном со сложным пользовательским интерфейсом, миксин для генерации стилей вкладок (tabs) принимает 18 параметров. Очевидно, что преимущества LESS в больших проектах сильно обесцениваются отсутствием именованных параметров.

Решение


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

Стили LESS

/* переменные */
@f-border-width: 4px;
@f-border-style: solid;
@f-border-color: #BE2;

/* объявляем миксин */
/* параметры по-умолчанию - переменные */
.f-border (
        @width: @f-border-width, 
        @style: @f-border-style,
        @color: @f-border-color
    ) {
    border: @width @style @color;
}

/* вызываем миксин без параметров */
.base-1 {
    .f-border;
}

/* изменяем переменную только в области видимости */
/* вызываем миксин без параметров */
.extension {
    @f-border-color: #F16;
    .f-border;
}

/* вызываем миксин без параметров */
.base-2 {
    .f-border;
}


Результат


Исходный код в jsFiddle.net.

Примечания:

* На официальном сайте LESS сказано, что «переменные на самом деле являются константами, так как не могут быть переопределены». Но есть и другая точка зрения.
** Несмотря на то, что у перевода оригинального «mixin» как «примесь» есть сторонники, более органичным для языка является заимствование терминов вместе с технологией, так как заимствование получается идентичным по смыслу, без внешних контекстов.
*** Для работы с LESS на jsFiddle.net необходимо через ресурсы подключить файл less.js, а в панель редактирования javascript добавить две строчки
document.getElementsByTagName('head')[0].getElementsByTagName('style')[0].type = 'text/less';
less.refreshStyles();
Share post

Similar posts

Comments 9

    +1
    Есть ли возможность скомпилировать *.css используя less файл и не устанавливая node.js?
    0
    В примере, указанном в статье, компиляция в CSS происходит на стороне клиента. Очевидно, что установки Node.js при этом не требуется. Если необходимо просто взглянуть на результат компиляции, то в этом примере показано как это сделать.

    Only users with full accounts can post comments. Log in, please.