Динамически определять переменную в LESS CSS

Я пытаюсь создать mixin, который динамически определяет переменные в LESS CSS, фактически присваивая им составное имя.

Упрощенный вариант использования (а не реальный):

.define(@var){
    @foo{var}: 0;
}

Тогда можно было бы назвать mixin как таковой:

.define('Bar'){
    @fooBar: 0;
}

Поскольку такой тип интерполяции строк возможен при использовании имен селекторов, мне было интересно, возможно ли такое же, что и для имен переменных; до сих пор мне не повезло с различными синтаксисами, которые я пробовал (кроме вышеперечисленного, я попытался экранировать, процитировать, используя префикс ~ и т.д.).

Изменить

Я просто попробовал еще одну вещь, и я чувствую, что могу быть рядом; но я испытываю странность синтаксиса LESS. Если я напишу это:

.define(@var){
    #namespace {
         @foo: @var;
    }
}

И затем назовите его так:

.define(0)

Затем я могу использовать @foo в обычном пространстве имен:

.test {
     #namespace;
     property: @foo; /* returns 0 */
}

Однако то же самое не применяется в случае селектора с интерполяцией строк:

.define(@var, @ns){
    #@{ns} {
         @foo: @var;
    }
}

.define(0, namespace);

.test {
     #namespace;
     property: @foo;
}

Приведенный выше код дает мне следующую ошибку:

Ошибка имени: #namespace undefined

Однако интерполяция строк была успешной и действительной. На самом деле, если я заберу часть .test и изменю приведенное выше, чтобы вывести тестовое свойство, я вижу, что CSS правильно разбирается. Я имею в виду:

.define(@var, @ns){
    #@{ns} {
         @foo: @var;
         prop: @foo;
    }
}

.define(0, namespace);

Выводит следующий CSS:

#namespace {
    prop: 0;
}

Ответ 1

Это невозможно сделать

То, что вы хотите сделать, в настоящее время невозможно в LESS. Я могу подумать о двух возможных "обходных решениях" , если вы заранее знаете, какие имена переменных вы хотите разрешить использовать (другими словами, не полностью динамические). Тогда можно сделать что-то вроде одного из следующих:

Идея №1 (переменные переменные)

.define(@var) {
  @fooBar: 0;
  @fooTwo: 2;
  @fooYep: 4;

  @fooSet: '[email protected]{var}';
}

.define(Two);
.test {
  .define(Bar);
  prop: @@fooSet;
}
.test2 {
  prop: @@fooSet;
}

Идея № 2 (параметрические миксы)

МЕНЬШЕ

.define(@var) {
  .foo() when (@var = Bar) {
    @fooBar: 0;
  }
 .foo() when (@var = Two) {
    @fooTwo: 2;
  }
 .foo() when (@var = Yep) {
    @fooYep: 4;
  }
  .foo();
}

.define(Two);
.test {
  .define(Bar);
  prop: @fooBar;
}
.test2 {
  prop: @fooTwo;
}

Выход CSS (для обеих идей)

.test {
  prop: 0;
}
.test2 {
  prop: 2;
}

Заключение

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

Ответ 2

Я не уверен, что вы хотите использовать это, но одно из моих предложений основано на ответе @ScottS. В моем реальном мире мне нужно создать веб-приложение, в котором будет показано, что несколько брендов и каждый бренд имеют свой собственный цвет текста, фон и т.д.... поэтому я начал преследовать способ выполнить это в LESS, что я можно легко сделать на SASS, и результат будет ниже:

МЕНЬШЕ

// Code from Seven Phase Max
// ............................................................
// .for
.for(@i, @n) {.-each(@i)}
.for(@n)     when (isnumber(@n)) {.for(1, @n)}
.for(@i, @n) when not (@i = @n)  {
    .for((@i + (@n - @i) / abs(@n - @i)), @n);
}

// ............................................................
// .for-each

.for(@array)   when (default()) {.for-impl_(length(@array))}
.for-impl_(@i) when (@i > 1)    {.for-impl_((@i - 1))}
.for-impl_(@i)                  {.-each(extract(@array, @i))}


// Brands
@dodge : "dodge";
@ford : "ford";
@chev : "chev";

// Colors
@dodge-color : "#fff";
@ford-color : "#000";
@chev-color : "#ff0";

// Setting variables and escaping than
@brands: ~"dodge" ~"ford" ~"chev";

// Define our variable   
.define(@var) {
  @brand-color: '@{var}-color';
}

// Starting the mixin
.color() {
    // Generating the loop to each brand
    .for(@brands); .-each(@name) {
        // After loop happens, it checks what brand is being called
        .define(@name);
         // When the brand is found, match the selector and color
        [email protected]{name} & {
            color: @@brand-color;
        }
    }
}

.carColor {
    .color();
}

Результат Te будет:

CSS

.brand-dodge .carColor {
    color: "#fff";
}
.brand-ford .carColor {
    color: "#000";
}
.brand-chev .carColor {
    color: "#ff0";
}

Это очень сложно, и я должен был использовать несколько элементов, чтобы получить то, что мне было нужно, сначала использовал набор mixins, предоставленный Seven Phase Max, и вы можете найти его здесь и чем, ответ @ScottS был частью, отсутствовавшей в моей головоломке... надеюсь, что это поможет вам и другим, которые должны создать набор переменных, чтобы быть частью другой переменной и создать более динамичный меньше файла.

Вы можете скопировать весь мой код и проверить его на http://lesstester.com/

Ответ 3

Чтобы следить за принятым ответом, вы также можете определить значение для переменной путем расширения .define() mixin следующим образом. Это позволяет использовать временный набор переменных внутри правила.

.define(@var, @val) {
  .foo() when (@var = temp1) {
    @temp1: @val;
  }
 .foo() when (@var = temp2) {
    @temp2: @val;
  }
 .foo() when (@var = temp3) {
    @temp3: @val;
  }
  .foo();
}

.define(temp2, 2);
.test {
  .define(temp1, 0);
  prop: @temp1;
}
.test2 {
  prop: @temp2;
}

Выход CSS

.test {
  prop: 0;
}
.test2 {
  prop: 2;
}

Вот более сложный принцип использования этого в mixin для генерации мгновенных фоновых изображений с фоном: обложка; (и резерв IE8).

Ответ 4

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

@whitelabel: 'foo';
@import 'whitelabel/@{whitelabel}/colors';