11

I am looking to do a for loop inside of Less. Is it possible to do this inside of Less? I know it has the capability to evaluate js but to this degree?

Steven Walker
  • 123
  • 1
  • 7
  • 1
    LESS is merely a CSS precompiler. The end result is plain CSS. I don't see where Javascript comes into it? – Pekka Aug 29 '11 at 05:19
  • 2
    @Pekka: LESS can execute dynamically, both client-side in the browser and server-side via Node.js ([more here](http://lesscss.org/)). Part of its syntax is indeed to evaluate a JavaScript expression, for example (client-side): `@height: \`document.body.clientHeight\`;` – T.J. Crowder Aug 29 '11 at 05:27
  • @T.J. ah, what do you know! Interesting, thanks. – Pekka Aug 29 '11 at 05:28

3 Answers3

23

I will recommend to checkout Twitter Bootsrap. They are building their grid system that way. They loop, with recursion, in a less mixin, instead of typing every class they need.

The interesting part is in mixins.less file, in the less directory, below "// The Grid" comment (line 516). The interesting portion is:

#grid {

    .core (@gridColumnWidth, @gridGutterWidth) {

      .spanX (@index) when (@index > 0) {
        (~".span@{index}") { .span(@index); }
        .spanX(@index - 1);
      }
      .spanX (0) {}

      ...

      .span (@columns) {
        width: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns - 1));
      }
 ...

Which is called in grid.less file in less directory this way:

#grid > .core(@gridColumnWidth, @gridGutterWidth);

Which produce (among other things):

.span12 {
  width: 940px;
}
.span11 {
  width: 860px;
}
.span10 {
  width: 780px;
}
...

in bootstrap.css line 170.

For @gridColumnWidth, @gridGutterWidth and the rest of variables check variables.less file (line 184)

Be sure to have the last version of lessc node compiler installed.

AlessMascherpa
  • 682
  • 8
  • 20
  • 4
    Thank for that. If someone is having trouble understanding this / needs a more detailed explanation: http://blog.thehippo.de/2012/04/programming/do-a-loop-with-less-css/ – TheHippo Apr 29 '12 at 22:58
  • I just looked at this in Bootstrap last night and it blew my mind and then I had to implement it in my own grid library. So Awesome! – kalisjoshua Jun 05 '12 at 15:45
  • 1
    Glad you find it useful @kalisjoshua! Cheer up is always welcome :) – AlessMascherpa Jun 06 '12 at 10:28
  • Just a quick gottcha: .spanX(@index - 1) works, .spanX(@index -1) fails. – Hampus Ahlgren Mar 18 '13 at 16:54
  • Loops have changed in version 0.4.0 of lessc compiler `(~".span@{index}")` becomes `span@{index}` http://leafo.net/lessphp/docs/#selector_expressions – yunzen Sep 03 '13 at 10:14
  • You can find a spanish version of this answer here: [Análisis de Twitter Bootstrap: especificar estilos CSS de manera recursiva con LessCss](http://www.alessmascherpa.com/2012/04/analisis-de-twitter-bootstrap.html#.U_IE9rx_vv0) Hope it helps. – AlessMascherpa Aug 18 '14 at 13:55
2

There's nothing about loops in the docs, but since you can access JavaScript expressions via backticks, you could always define a function in your script (not your LESS code, but JavaScript — e.g., if in a browser, you'd have a separate script element) that does your loop and then access it, e.g.:

@height: `doMyLoop()`

It depends on what you're trying to achieve with the loop. If you want the loop to output CSS rules, I suspect you're out of luck.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    I am trying to create a loop that creates at 24 col grid. Basically, I want it to cycle through 24 times and write the grid classes. .grid_1, .grid_2, ...., .grid_24 – Steven Walker Sep 24 '11 at 02:03
  • This can be done with the example given by AlessMascherpa above with small mods, though the output steps down (10,9,8...) vs. up (1,2,3...), it works just a stylistic thing. – augurone Jul 30 '13 at 01:16
1

This is a hack but... Add this to your less file.

@testColor: green;

unusedclass {
    unknownprop: ~`loopCss(10,".group{{i}} { background-color: @{testColor}; }")`
}

Create a javascript file loopCss.js with the following function:

function loopCss(count,cssTemplate) {
    // end the existing unused class
    var result = "0;}\n";
    // Add your custom css
    for(var i=0; i<count; i++) result += cssTemplate.replace("{{i}}",i) +"\n";
    // Handle the close bracket from unused class
    result += "unusedclass {";
    return result;
}

Now include the loopCss.js before your less.js and it should work.

matsondawson
  • 738
  • 1
  • 4
  • 7