mixin 中的 LESS 设置变量

LESS setting variable inside mixin

为什么没有设置@nav-color...?

@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();

一旦在命名空间或混入中声明了一个变量,它就会变成范围内或只能在该命名空间内访问,并且它的值不能在范围外访问。

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).

解决方案一: 这种特殊情况的一种选择是使用未命名的命名空间 (&) 并在其中调用 mixin,如下所示:

@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.

解决方案 2: 删除 @nav-color 变量的默认值似乎可以使有问题的代码按原样工作。这应该不会产生任何问题,因为 .theme() mixin 的保护条件中的任何一个都将始终匹配,因此变量将始终分配一个值。

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

方案三: 解决这个问题的一种完全不同的方法是使用 seven-phases-max in this answer 提到的内置 contrast() 函数来完全避免混入,并直接根据另一个变量的亮度或暗度设置变量值。


附加信息: 为了进一步说明这一点,下面的代码可以正常工作(尽管它不是您所追求的)并且会输出正确的颜色,因为 @nav-color 的值设置在其范围内。

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