Use Selector Name as Variable in Less Mixin

Use selector name as variable in LESS mixin

You cannot "read" the selector name.

However, you can build the selector in conjunction to linking with the file name in a mixin, something like so:

LESS

.buildSelectorConnection(@selectorName, @pre: ~'') {
@{pre}@{selectorName} {
background-image: url('images/@{selectorName}.png');
}
}

.buildSelectorConnection(header, ~'#');
.buildSelectorConnection(do-a-class, ~'.');

CSS Output

#header {
background-image: url('images/header.png');
}
.do-a-class {
background-image: url('images/do-a-class.png');
}

However, it would take quite a bit more logic, decision making on your part, and some javascript coding in LESS if you wanted to make such a thing be able to handle something like div#menu ul li where the actual filename generated was something like div-menu-ul-li.png.

Nevertheless...

Something like this could be done:

LESS

.buildSelectorConnection(@selectorName, @pre: ~'', @post: ~'') {
@{pre}@{selectorName}@{post} {
background-image: url('images/@{selectorName}.png');
}
}

.buildSelectorConnection(menu, ~'div#', ~' ul li');

CSS Output

div#menu ul li {
background-image: url('images/menu.png');
}

This basically lets you build any selector string, but the file name itself will only be that initial selector passed in, which needs to be something valid for a file name.

Using variable name for selector in less

Yes, this can be done

This works in LESS 1.3.1+. You can vary the string, but this is simply an example of one way it could be done:

LESS

@selector1: ~'#master';
@selector2: ~'@{selector1} #leftcontent';
@selector3: ~'@{selector1} #rightcontent';

@{selector2} div,
@{selector3} div {
background-color: #fff;
}

@{selector2} a,
@{selector3} a {
color: blue;
}

CSS Output is exactly as you show in the question.

use variables on mixin or extend in Less.js

You are trying to call a mixin using selector interpolation, which is not possible.

As for extend, Less documentation states it clearly:

Extend is NOT able to match selectors with variables. If selector contains variable, extend will ignore it.

LESS mixin returning a custom variable name

You can store the variable name in a variable and call it with two @@variable. You would have to store the name of the inner variable somewhere, though. You could try something like this:

.fadeColor(@name; @color: #000; @opacity: 1) {
@return: rgba(red(@color), green(@color), blue(@color), @opacity);
}

.class1 {
@name: return;
.fadeColor(@name; blue; 1);
border-color: @@name;
}

.class2 {
@myColor: return;
@myBG: return;
&{
.fadeColor(@myColor, #f00, .5);
color: @@myColor;
}
&{
.fadeColor(@myBG, #00f, .7);
background: @@myBG;
}
}

which will produce:

.class1 {
border-color: #0000ff;
}
.class2 {
color: rgba(255, 0, 0, 0.5);
background: rgba(0, 51, 255, 0.7);
}

Probably that introduces a lot of unnecessary code. I don't know what you are trying to do, but you can probably find better ways to achieve what you want without requiring a mixin to return a value. You could, for example, send the property as a parameter:

.fadeColor(@property; @color: #000; @opacity: 1) {
@{property}: rgba(red(@color), green(@color), blue(@color), @opacity);
}

.class2 {
.fadeColor(color, #f00, .5);
.fadeColor(background, #00f, .7);
}

In Less 1.7.0 you can store complete rulesets in variables (see: detached rulesets feature). You might want to experiment with it.

LESS mixin a variable class name

There are at least 2 problems with what you are trying to do (for LESS >=1.6 see update bellow):

1) Unfortunately it is not possible to call a mixin using selector
interpolation.

With selector interpolation LESS expects the construct to be of
following format:

.@{selector-string} { property:value; }

(the interpolated selector can have also some static string pre or
post the interpolation)

so

.@{selector-string};

is Unrecognised by the LESS compiler. See more here:
How can I call a mixin by reference in LESS?

2) A ruleset with an interpolated selector gets directly printed to the CSS output and does not exist as a mixin that you could reuse in the LESS run

For example:

@foo: test;

.@{foo} {
length: 20px;
}

.bar {
.test;
}

will return:

    Name error: .test is undefined
.bar { .test;}

See more on that here: LESS CSS: Reuse generated .@{name} class as a mixin

Possible solution for your problem would be redifinig the font awesome rules as some kind of reusable mixins (without using interpolation). Something like this:

@fa-var-github: "\f09b";

.fa-mixin() {
display: inline-block;
font-family: FontAwesome;
font-style: normal;
font-weight: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.fa-mixin-lg() {
font-size: (4em / 3);
line-height: (3em / 4);
vertical-align: -15%;
}
.fa-mixin-icon(@icon){
@var: "fa-var-@{icon}";
&:before { content: @@var; }
}
i {
.fa-mixin;
.fa-mixin-lg;
.fa-mixin-icon(github);
}

If you don't really need the variables and just want to include the rules, the best way would be just to import the compiled CSS version of the FontAwesome (see answer here):

@import (less) 'font-awesome.css';

and then you can just use the CSS rules like LESS mixins or extend their selectors as you see fit and it should work perfectly.


Update:

As of LESS >= 1.6 rules with interpolated selectors can be accessed as mixins ... so the #2 limitation form above does not apply anymore (but you still can not call a mixin dynamically with interpolation). So you can simply call LESS mixins and variables from the imported font-awesome.less file like so:

i {
.fa;
.fa-lg;
&:before{
content: @fa-var-github;
}
}

Use mixin argument to create class name in LESS

I think I have the solution using Variable Names.

Less

@green: #5FBEAA;

.text-color(@colorname) {
@color: ~"@{colorname}";
.text-@{color}{
color: @@color;
}
}

.text-color(green);

Output

.text-green {
color: #5FBEAA;
}


Related Topics



Leave a reply



Submit