0

I'm not quite sure how to describe this so I'll do my best to give a good example. My situation is something like this:

@var: ~"a";
@blah: ~"body > header > @{var} > strong > em";

@{blah} {
    color: red;
}

which outputs

body > header > a > strong > em {
    color: red;
}

but what if you want to add something like @var: ~"a, a:hover" how would you get it to ouput this?

body > header > a > strong > em,
body > header > a:hover > strong > em {
  color: red;
}
joshhunt
  • 5,197
  • 4
  • 37
  • 60
  • 2
    Could you not use nested rules instead? – BoltClock Aug 07 '14 at 03:04
  • Why not like [this](http://codepen.io/hari_shanx/pen/etKGH)? Basically similar to BoltClock's comment above. – Harry Aug 07 '14 at 03:08
  • I could use nested rules but I was wondering if it's possibly to do it another way. I'm being challenged to a LESS vs PHP duel and so far I'm losing. – joshhunt Aug 07 '14 at 03:21
  • @joshhunt: I wouldn't really recommend this second approach. But if you really have no way, you could use regex/string replace (as Less can evaluate JS code) like [this](http://codepen.io/hari_shanx/pen/etKGH). – Harry Aug 07 '14 at 03:33
  • 1
    Well, in short you can't use lists for selector interpolation (see [#1694](https://github.com/less/less.js/issues/1694)). I also would suggest some plain nesting (like [this](https://gist.github.com/seven-phases-max/47ebdd3e276a2b5dd09d#file-25173448-1-less)). Although, if you need to move the list out of actual selector statement *that bad* - there's a scary way: see http://stackoverflow.com/questions/24407388 (For your example it would probably look something like [this](https://gist.github.com/seven-phases-max/e20c5b663f76110fdacf#file-25173448-2-less), req. Less 1.7.x). – seven-phases-max Aug 07 '14 at 04:20
  • Also if you could describe more about why exactly "Less vs PHP duel" *dictates* to use "another way" we could suggest something else? – seven-phases-max Aug 07 '14 at 04:22
  • You guys have been very helpful thanks! So I think in conclusion 1. you can't use lists for selector interpolation 2. nested rules would work just as well anyways. Pretty much he was showing me php examples which he was trying to get me to duplicate in less. I guess instead of trying to directly duplicate it I should have been looking for another way to do the same thing (such as nesting). – joshhunt Aug 07 '14 at 04:28
  • Ah, I see now. Well, there's nothing bad in losing "Less" vs "PHP as CSS-preprocessor" comparison. Less is designed as minimalistic, simple and *readable* extension to CSS (keeping in mind those who don't want to bother with other programming languages *at all*). Obviously a text-preprocessor which just replaces any arbitrary text with any other may be considered more powerful for special cases just by definition. You just never compare a non-comparable things. – seven-phases-max Aug 07 '14 at 04:49
  • @seven-phases-max: Wow, that took me 30 minutes to decipher :D. By the way, any speical reason for `@-: >;`? Wouldn't just doing a `>` in the selector after `header` itself do the job? – Harry Aug 07 '14 at 04:52
  • 1
    `@-: >;` - yes, by now any selector can only have `combinator identifier` form (a combinator not followed by an identifier is simply ignored, i.e. `body > {...` will be compiled to `body {...`). I suppose this limitation is actually kind of bug/issue and will be improved eventually. – seven-phases-max Aug 07 '14 at 05:07
  • Ah, and just in case, there's another method - using `extend`, it's much more clean if you don't mind dummy selectors in the final CSS: [gist](https://gist.github.com/seven-phases-max/e9162479b1b73389e8e3#file-25173448-3-less). – seven-phases-max Aug 07 '14 at 06:01

2 Answers2

1

See also: https://github.com/less/less.js/issues/2263

If you are enable to split @var into two (or more) separated variables you can use the following Less code:

@var1: ~"> a";
@var2: ~"> a:hover";
body > header {@{var1},@{var2} { > strong > em {color:red;}}}

The preceding will compile into the following CSS code:

body > header > a > strong > em,
body > header > a:hover > strong > em {
  color: red;
}

When @var: "a", "a:hover"; you can also use:

@var1: e(extract(@var,1));
@var2: e(extract(@var,2));

body > header {
  > @{var1}, > @{var2} {
    > strong > em {
      color: red;
    }
  }
}

Or use a complex mixin (as Bootstrap does, see: LESS loops used to generate column classes in twitter - How do they work?) to build your selectors:

.mixin(@iterator: 0; @selectors: ~""; @seperator: ~"") when (@iterator < length(@var)) {
  @blah: ~"body > header > @{selector} > strong > em";
  @selector: extract(@var,@iterator + 1);
  @selectorlist: ~"@{selectors} @{seperator} @{blah}";
  .mixin((@iterator + 1); @selectorlist; ~",");
}
.mixin(@iterator; @selectors: ~""; @seperator: ~"") when (@iterator = length(@var)) {
  @{selectors} {
    color:red;
  }
}
.mixin();
Community
  • 1
  • 1
Bass Jobsen
  • 48,736
  • 16
  • 143
  • 224
1

Just in case I'll put "the readable" solution from comments above:

// "variables":

a, a:hover {
    &:extend(.var all);
}

body > header > .var > strong > em 
    :extend(.blah) {}

// usage:

.blah {
    color: red;
}

One of extends is redundant actually and I used it only to resemble the structure of the original snippet (i.e. var to blah "connection").

seven-phases-max
  • 11,765
  • 1
  • 45
  • 57