LESS setting variable inside mixin

2019-09-01 07:50发布

问题:

Why is @nav-color not getting set...?

@light: #f5f5f5;
@nav-color: #0ff;
@headerbar: #333;  
@dark: #222;
@light: #f5f5f5;

.theme() when (lightness(@headerbar) > 50%) {
    @nav-color: @dark;
}
.theme() when (lightness(@headerbar) <= 50%) {
    @nav-color: @light;
}
.theme();

回答1:

Once a variable is declared within a namespace or a mixin, it kind of becomes scoped or accessible only within that namespace only and it's value cannot be access outside of the scope.

Reference from Less Website: Note that variables declared within a namespace will be scoped to that namespace only and will not be available outside of the scope via the same syntax that you would use to reference a mixin (#Namespace > .mixin-name). So, for example, you can't do the following: (#Namespace > @this-will-not-work).

Solution 1: One of the options for this particular case would be to use an unnamed namespace (&) and call the mixin within it like below:

@light: #f5f5f5;
@nav-color: #0ff;
@headerbar: #333;  
@dark: #222;
@light: #f5f5f5;

.theme() when (lightness(@headerbar) > 50%) {
    @nav-color: @dark;
}
.theme() when (lightness(@headerbar) <= 50%) {
    @nav-color: @light;
}

&{
    .theme();
    div#sample1{
        color: @nav-color;
    }

    div#sample2{
        background-color: @nav-color;
    }
}

All the following options are courtesy of [seven-phases-max]'s comment and are added to the answer for completeness sake.

Solution 2: Removing the default value for the @nav-color variable seems to make the code in question work as-is. This should not create any issues because either one of the .theme() mixin's guard conditions would always be matched and hence the variable would always get a value assigned.

@light: #f5f5f5;
@headerbar: #333;  
@dark: #222;
@light: #f5f5f5;

.theme() when (lightness(@headerbar) > 50%) {
    @nav-color: @dark;
}
.theme() when (lightness(@headerbar) <= 50%) {
    @nav-color: @light;
}
.theme();

div#sample1{
    color: @nav-color;
}

Solution 3: A completely different approach to solve this problem would be to use the built-in contrast() function mentioned by seven-phases-max in this answer to totally avoid the mixin and set the variable values directly based on the lightness or darkness of another variable.


Additional Information: To further illustrate the point, the below would work fine (though it is not exactly what you are after) and would output the correct color because the value for the @nav-color is set within its scope.

.theme() when (lightness(@headerbar) > 50%) {
    @nav-color: @dark;
    div#sample3{
        border-color: @nav-color;
    }    
}
.theme() when (lightness(@headerbar) <= 50%) {
    @nav-color: @light;
    div#sample3{
        border-color: @nav-color;
    }       
}


标签: less