Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic class names in LESS

I have the following bit of LESS code working

            @iterations: 940;
            @iterations: 940;
            @col:2.0833333333333333333333333333333%;
            // helper class, will never show up in resulting css
            // will be called as long the index is above 0
            .loopingClass (@index) when (@index > -20) {
                // create the actual css selector, example will result in
                // .myclass_30, .myclass_28, .... , .myclass_1
                (~".gs@{index}") {
                    // your resulting css
                    width: (@index/20+1)*@col;
                }
                // next iteration
                .loopingClass(@index - 60);
            }
            // end the loop when index is 0
            .loopingClass (-20) {}
            // "call" the loopingClass the first time with highest value
            .loopingClass (@iterations);

It outputs our grid system as so:

            .gs940 {
              width: 100%;
            }
            .gs880 {
              width: 93.75%;
            }
            .gs820 {
              width: 87.5%;
            }
            .gs760 {
              width: 81.25%;
            }
            .gs700 {
              width: 75%;
            }

etc etc etc

Now what I want to do is some math to the class names to produce the following classes

            .gs220-700
            .gs280-640
            .gs340-580
            .gs400-520
            .gs460-460
            .gs520-400
            .gs580-340
            .gs640-280
            .gs700-220

etc etc etc

basically this would be .(@index) - (920px minus @index)

But I have no idea if this is possible.

like image 458
R Reveley Avatar asked Jun 05 '12 14:06

R Reveley


2 Answers

This whole question was very helpful to me. I just wanted to post the solution to my problem as the way to do it has changed since LESS v 1.4. LESS Changelog

Rather than using the ~ sign, you just write out the portion of the name that you want along with the normal @ and variable name with {} surrounding it. So: #class@{variable}.

For example, my solution using the same sort of loop became such:

/*Total number of passport inserts*/
@numInserts: 5;
/*Total width of the passport foldouts*/
@passportWidth: 300px;
/*Change in passport insert width per iteration*/
@passportWidthDiff: (@passportWidth / @numInserts);
/*"Array" of colors to select from to apply to the id*/
@passportColors: 
blue orange green red yellow 
purple white teal violet indigo;

/*The faux loop the doesn't end up in the final css
@index is the counter
@numInserts is the total number of loops*/
.loopingClass (@index) when (@index <= @numInserts){
   /*This is the created ID with the index appended to it
   You can also do this with classes such as if 
   we had had ".insert@{index}"*/
   #insert@{index}{
      /*Here are our properties that get adjusted with the index*/
      width: (@passportWidth - (@passportWidthDiff * (@numInserts - @index)));
      height: 50px;
      background-color: extract(@passportColors, @index);
      z-index: (@numInserts - @index);
   }
   /*Here we increment our loop*/
   .loopingClass(@index + 1);
}
/*This calls the loop and starts it, I started from 1
since I didn't want to lead a className starting from 0,
But there is no real reason not to.  Just remember to
Change your conditional from "<=" to "<"*/
.loopingClass(1);

And produces the following:

#insert1 {
  width: 60px;
  height: 50px;
  background-color: #0000ff;
  z-index: 4;
}
#insert2 {
  width: 120px;
  height: 50px;
  background-color: #ffa500;
  z-index: 3;
}
#insert3 {
  width: 180px;
  height: 50px;
  background-color: #008000;
  z-index: 2;
}
...
like image 101
zero298 Avatar answered Nov 09 '22 04:11

zero298


I don't think you're far off. What I've done is create a second variable inside the mixin, called @index2. All this does is find the '920px minus @index' value that you're looking for:

@index2 = (920-@index);

this is then appended to the class name:

(~".gs@{index}-@{index2}") {

This is the complete loop:

.loopingClass (@index) when (@index > 160) {
    @index2 = (920-@index);
    // create the actual css selector, example will result in
    // .myclass_30, .myclass_28, .... , .myclass_1
    (~".gs@{index}-@{index2}") {
    // your resulting css
        width: (@index/20+1)*@col;
    }
    // next iteration
    .loopingClass(@index - 60);
}
// "call" the loopingClass the first time with highest value
.loopingClass (@iterations);

In order to get just the set you are looking for (gs220-700 to gs700-220), just change @iterations to equal 700.

Worth noting that currently, this will create the classes in the reverse order of how you specified them in the question.

like image 21
cchana Avatar answered Nov 09 '22 04:11

cchana