Less Mixin a Variable Class Name

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;
}

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;
}
}

How to pass multiple class names to a mixin in LESS

Option 1:

As you mentioned, one option is to pass the value within quotes. But when that is done, you need to make sure to remove them before using them to perform selector interpolation. This can be done by either using the ~() or the e() built-in functions. Both of them will strip out the quotes from the input value. Once this is done, the temporary variable whose value doesnt have the quotes can be used for selector interpolation like below:

.transaction-status(@class, @color) {
@className: ~"@{class}";
table#transactions > tbody > tr@{className} {
color: @color;
}

table#legend > tbody > tr > td@{className} {
color: @color;
}
}

.transaction-status(".credit", limegreen);
.transaction-status(".debit.paid", goldenrod);
.transaction-status(".debit.unpaid", crimson);

Option 2: (a bit round about in my opinion)

You can also use the ... option to pass in as many classes as required (note that this needs a small change to the order in which the inputs are passed) and then convert it to a string and use the replace function to add the .. The replace function is required because the converted string would be of the format class1 class2 (space separator).

.transaction-status(@color, @class...) {
@className: e(replace("@{class}" , " " , ".", 'g' ));
/* arguments: input string, pattern to match, replacement value, regex flags */
table#transactions > tbody > tr.@{className} {
color: @color;
}

table#legend > tbody > tr > td.@{className} {
color: @color;
}
}

.transaction-status(limegreen, credit);
.transaction-status(goldenrod, debit, paid);
.transaction-status(crimson, debit, unpaid);

Note: Option 2 would work only with Less v.1.7.0 and above because the replace function was introduced only in v1.7.0.

Dynamic class names in LESS

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.

Less - Defining a class name that conflicts with mixin

This should not be a problem. This is bootstrap's placeholder mixin

// Placeholder text
.placeholder(@color: @input-color-placeholder) {
&:-moz-placeholder { color: @color; } // Firefox 4-18
&::-moz-placeholder { color: @color; // Firefox 19+
opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526
&:-ms-input-placeholder { color: @color; } // Internet Explorer 10+
&::-webkit-input-placeholder { color: @color; } // Safari and Chrome
}

This is not a mixin class, as it has parenthesis after it. Therfore it will not output anything unless it is referenced. To use this I would need to do something like this.

.input {
.placeholder;
}

Therefore this will not interfere with any .placeholder class you may have.

.placeholder {
color: red;
}

The two should happily co-exist and you should not get any problems.

Edit: see comments

The solution was to use multi class selector to overcome the issue.

Example

.input.placeholder {
color: red;
}

Variable Concatenation - using a mixin to dynamically create class name

@classname: ~'@{varone}_@{vartwo}'; (or same with double quotes) is the correct syntax and works in all conformant Less compilers. I.e.:

.createClass() {
@varone: one;
@vartwo: two;
@classname: ~'@{varone}_@{vartwo}';

.testClass_@{classname} {
padding: .5em;
}
}

.createClass();

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 CSS: Reuse generated .@{name} class as a mixin

Unfortunately. The selector interpolation is just string interpolation, and the string gets then printed into css, so no class object is generated in the less run.

So you can design a generator/mixin, that includes your operation:

#genMarginTop (@size) {
margin-top: @size;
}

But then build classes by calling the mixins / generators:

.mtStandard {#genMarginTop(40px);}
.mtHalf {#genMarginTop(20px);}

And this way they are class objects that you can use for mixin =)

.someClass {
background-color: #FFF;
.mtStandard;
//more of this stuff
}

This looks a bit silly in this simple example, but maybe something like this:

 #bggenerator (@color) {
background-color: @color;
}
#bggenerator (@color, dark) {
@blend : @color + #842210;
background-color: darken(@blend, 30%);
}
#bggenerator (@color, @url, @rest) {
background: "@{color} url('@{url}') @{rest}";
}

.mtStandard {
#genMarginTop(40px);
}

.someClass {
.mtStandard;
#bggenerator(#FFF, "bgimage.png", left top no-repeat);
//more of this stuff
}

Or something that does even more exciting stuff with the arguments



Related Topics



Leave a reply



Submit