Динамически определять переменную в 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';