Loop over an array of name value pairs in LESS

人盡茶涼 提交于 2019-11-26 17:47:06
Bass Jobsen

The answer given by @seven-phases-max works very well. For completeness you should also notice that you can do the same in Less without the imported "for" snippet.

from lesscss.org

In trying to stay as close as possible to the declarative nature of CSS, Less has opted to implement conditional execution via guarded mixins instead of if/else statements, in the vein of @media query feature specifications.

and

In Less a mixin can call itself. Such recursive mixins, when combined with Guard Expressions and Pattern Matching, can be used to create various iterative/loop structures.

So in Less you could write:

@array: alice black, bob orange;

.createcolorclasses(@iterator:1) when(@iterator <= length(@array)) {
    @name: extract(extract(@array, @iterator),1);
    .cl-@{name} {
        background-color: extract(extract(@array, @iterator),2);
    }
    .createcolorclasses(@iterator + 1);
}
.createcolorclasses();

or indeed:

@array: alice black, bob orange;

.createcolorclasses(@iterator:1) when(@iterator <= length(@array)) {
    @name: extract(extract(@array, @iterator),1);
    &@{name} {
        background-color: extract(extract(@array, @iterator),2);
    }
    .createcolorclasses(@iterator + 1);
}
.cl-{
    .createcolorclasses();
}
seven-phases-max

In Less a "pair" (in its simplest form) can be represented as an array too, so it can be as simple as:

@import "for";

@array: alice black, bob orange;

.for(@array); .-each(@value) {
    @name:  extract(@value, 1);
    @color: extract(@value, 2);
    .cl-@{name} {
        background-color: @color;
    }
}

Note however that the ".for" thing is limited to the only loop per scope so it's better to rewrite above to something like this:

@import "for";

@array: alice black, bob orange;

.cl- {
    .for(@array); .-each(@value) {
        @name:  extract(@value, 1);
        &@{name} {
            background-color: extract(@value, 2);
        }
    }
}

The imported "for" snippet (it's just a wrapper mixin for recursive Less loops) can be found here (with examples here and here).

While it is useful from the other answers to know that Less supports recursive functions and mixins, there is now a much simpler answer to this simple question. This solution is tested to work with Less v3.9, but should work back to Less v3.7 when each was introduced.

.array() {
  alice: black;
  bob: orange;
}

each(.array(), {
  .cl-@{key} {
    background-color: @value;
  }
});

The output is tidy:

.cl-alice {
  background-color: black;
}

.cl-bob {
  background-color: orange;
}

Want more? Well, as they say, "You can haz more". Use @index to use the 1-based index in the formula above.

Here is one "parametric mixins" which you can use with "key:value" pairs.

Array of "key:value" pairs is defined as follows: @array: "key:value", "key:value";

// imported "for" snippet (it's just a wrapper mixin for recursive Less loops)
// http://is.gd/T8YTOR
@import "for";

// loop all items and generate CSS
.generate_all(@array) {
    .for(@array);
    .-each(@item) {
        @name: e(replace(@item, ':(.*)', ''));
        @value: replace(@item, '^[^:]*:', '');
        @{name} {
            z-index: e(@value);
        }
    }
}

Definition:

@array_test: ".test:9000", "header .mainNav:9000", "footer:8000", "li.myclass:5000";

Test

.generate_all(@array);

Result:

.test {
  z-index: 9000;
}
header .mainNav {
  z-index: 8000;
}
footer {
  z-index: 7000;
}
li.myclass {
  z-index: 5000;
}

It works for me using grunt + less@1.7.4

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!