Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically generate an entire class and concatenate it to its parent selector using LESS

Tags:

css

less

So far I have this (LESS language):

LESS:

.test(@name) {
    (~".sm-@{name}") {
        background: ~"url(../images/icons/sm/@{name}-16x16.png)";
    }
}

and I can call it (.test("facebook")) to generate something like this:

CSS:

.sm-facebook {
    background: url(../images/icons/sm/facebook-16x16.png);
}

However, I'm not able to concatenate this generated class definition to a parent selector using the usual & operator. I would expect

LESS:

ul {
    li {
        &.test("facebook");
    }
}

to generate

CSS:

ul li.sm-facebook {
    background: url(../images/icons/sm/facebook-16x16.png);
}

but I am getting a parse error.

How can I do this?

like image 717
eepp Avatar asked Apr 27 '13 22:04

eepp


1 Answers

A LESS 1.4 Answer

At the time of initial answer, I had not resolved if there is a way to do this in LESS 1.3.3 (but later did, see update below). I had found that the current LESS 1.4 (beta) can achieve it by putting the concatenation in the mixin itself this way (note the lack of quotes on the argument):

LESS

.test(@name) {
    &.sm-@{name} {
        background: ~"url(../images/icons/sm/@{name}-16x16.png)";
    }
}

ul{
  li {
    .test(facebook);
  }
}

CSS Output

ul li.sm-facebook {
  background: url(../images/icons/sm/facebook-16x16.png);
}

If you need flexibility to have it concatenate or not, you can do a nested mixin like so (this one defaults to attach):

.test(@name, @attach: 1) {
    .attach(1) {
      &.sm-@{name} {
        background: ~"url(../images/icons/sm/@{name}-16x16.png)";
      }
    }
    .attach(0) {
      .sm-@{name} {
        background: ~"url(../images/icons/sm/@{name}-16x16.png)";
      }
    }
   .attach(@attach);
}

Then use it like this .test(facebook); to concatenate, and this .test(facebook, 0); to separate it as a child (or standalone) class.

Update: A LESS 1.3.1 to 1.3.3 Answer

Change the name first so that the string evaluation is separate from the class name assignment. Other points made above about flexibility can be used for this answer as well.

.test(@name) {
  @addName: ~"sm-@{name}";
  &.@{addName} {
        background: ~"url(../images/icons/sm/@{name}-16x16.png)";
    }
}
like image 104
ScottS Avatar answered Oct 22 '22 08:10

ScottS