本文介绍的是 less 中的条件表达式和循环。这两个概念和混入搭配使用可以极大的提升 less 代码的复用,提升代码的可维护性和通用性。是步入 less 高级使用不可错过的技巧!
1. 条件表达式
1.1 比较运算符
和 less 中相关的比较运算符有:> >= < <= true
这几个,也就是通常能够产生布尔值的符号。
1.2 语法格式
less 中的条件表达式,一般是结合 mixin 来使用的,具体来说,其语法可以简单的理解为在 mixin 后面添加额外的代码: when ()
表示对其作用范围的限制。
less
.mixin(@a) when (lightness(@a) >= 50%) {
background-color: @a;
}
.mixin(#ddd);
1.3 相关函数
要想 less 条件写得好,除了知道相关的运算符,还需要知道相关的函数,比如上面代码中的 lightness
函数。而之所以有这些函数,主要还是因为 css 中的属性值往往带有单位并且是复合属性。所以从字面量上很难计算,于是需要一种模式,将其中感兴趣的数据提取出来。
那么除了上面的 lightness
函数,比较常用的函数还有如下:
1.3.1 类型检测函数
iscolor
: 检测变量是不是合法的颜色值。isnumber
: 检测变量是不是数字。isstring
: 检测变量是不是字符串。iskeyword
: 检测是不是关键字。isurl
: 检测变量是不是合法的url。
less
// 自定义函数来模拟 iscolor
.iscolor(@value) when (iscolor(@value)) {
color-test: 'true';
}
.iscolor(@value) when (not iscolor(@value)) {
color-test: 'false';
}
// 自定义函数来模拟 isnumber
.isnumber(@value) when (isnumber(@value)) {
number-test: 'true';
}
.isnumber(@value) when (not isnumber(@value)) {
number-test: 'false';
}
// 自定义函数来模拟 isstring (Less中的变量通常都是字符串,这里主要是为了示例)
.isstring(@value) when (@value = '') {
string-test: 'true';
}
.isstring(@value) when not (@value = '') {
string-test: 'false';
}
// Less本身没有iskeyword或isurl的内置函数,所以我们可以通过正则表达式来简单模拟
// 这里只是示例,并没有实现完整的正则表达式匹配
.iskeyword(@value) when (@value = 'keyword') {
keyword-test: 'true';
}
.iskeyword(@value) when not (@value = 'keyword') {
keyword-test: 'false';
}
.isurl(@value) when (@value = 'http://example.com') {
url-test: 'true';
}
.isurl(@value) when not (@value = 'http://example.com') {
url-test: 'false';
}
// 使用示例
#test-area {
// 测试颜色
.iscolor(#ff0000); // 应该返回 'true'
color-test-red: @color-test;
.iscolor(notacolor); // 应该返回 'false'
color-test-notacolor: @color-test;
// 测试数字
.isnumber(123); // 应该返回 'true'
number-test-numeric: @number-test;
.isnumber(abc); // 应该返回 'false'
number-test-nonnumeric: @number-test;
// 测试字符串 (在Less中通常所有值都可以当作字符串处理)
.isstring('this is a string'); // 应该返回 'true',但这个示例可能不准确,因为Less处理值的方式与这个简单测试不完全相符
string-test-string: @string-test;
.isstring(123); // 即使传入数字,也可能返回 'true',这取决于Less如何将值解释为字符串
string-test-nonstring: @string-test;
// 测试关键字
.iskeyword(keyword); // 应该返回 'true',这里只是一个非常简单的示例
keyword-test-keyword: @keyword-test;
.iskeyword(notakeyword); // 应该返回 'false'
keyword-test-notakeyword: @keyword-test;
// 测试URL
.isurl('http://example.com'); // 应该返回 'true',这里只是一个示例,并没有实现完整的URL匹配逻辑
url-test-valid: @url-test;
.isurl('not a url'); // 应该返回 'false'
url-test-invalid: @url-test;
}
1.3.2 单位检测函数
ispixel
: 检测变量是不是合法的颜色值。ispercentage
: 检测变量是不是数字。isem
: 检测变量是不是字符串。isunit
: 检测是不是关键字。
less
// 示例:使用ispercentage函数
.test-percentage(@value) when (ispercentage(@value)) {
percentage-test: 'true';
}
.test-percentage(@value) when not (ispercentage(@value)) {
percentage-test: 'false';
}
#percentage-test {
.test-percentage(50%); // 返回 'true'
.test-percentage(50); // 返回 'false'
percentage-result: @percentage-test;
}
// 示例:使用isunit函数
.test-unit(@value) when (isunit(@value, px)) {
unit-test: 'true';
}
.test-unit(@value) when not (isunit(@value, px)) {
unit-test: 'false';
}
#unit-test {
.test-unit(10px); // 返回 'true'
.test-unit(10); // 返回 'false'
unit-result: @unit-test;
}
// 示例:检测一个值是否为字符串(在Less中,大多数值都可以视为字符串)
.test-string(@value) when (@value = '') {
string-test: 'true'; // 这里的判断逻辑比较简化,只是为了演示
}
.test-string(@value) when not (@value = '') {
string-test: 'false';
}
#string-test {
.test-string(''); // 返回 'true'
.test-string(not-empty); // 返回 'false'
string-result: @string-test;
}
// 注意:由于Less中并没有直接的isstring函数,上述的test-string函数只是为了演示目的。
// 在实际应用中,大多数传递给Less的值都可以被当作字符串处理。
// 假设的ispixel和isem函数并不是Less的内置函数,如果需要这样的功能,需要自定义混合(mixin)来实现。
1.4 结合检测函数和混入做重载
如下所示,结合能够发挥更大的威力!
2. 循环
less 中的循环是通过让 混合 来调用自身实现的;如果结合条件表达式和自增量就可以将这种递归的调用控制在一个合理的范围内,从而实现预定目的。
如下的代码能够反映出 less 中循环的巨大威力:
less
.posCommon(@w,@h,@t,@l,@pos:absolute) {
position: @pos;
left: @l;
top: @t;
width: @w;
height: @h;
}
.generate-content(@index:1,@params:@contentLefts) when (@index<=length(@contentLefts)) {
@left: extract(@params,@index);
.content@{index} {
.posCommon(14.90%, 25.00%, 71.57%, @left);
outline: 1px solid transparent;
}
.generate-content(@index+1);
}
.generate-content();
3. 合并属性
在使用 mixin 的时候难免会遇到这样的问题:
less
.mixin(){
box-shadow: inset 0 0 10px #555;
}
.myclass {
.mixin();
box-shadow: 0 0 20px black;
}
这样写,混合根本就不会有什么效果,因为 css 本质上是相互覆盖的;而上面的代码明显就是想要将两个 box-shadow
中的属性合在一起,这个时候可以使用合并属性 ,使用合并属性非常的容易,那就是在冒号之前加上 +
即可,写成:+:
less
.mixin(){
box-shadow+: inset 0 0 10px #555;
}
.myclass {
.mixin();
box-shadow+: 0 0 20px black;
}
编译之后的结果为:
less
.myclass {
box-shadow+: inset 0 0 10px #555, 0 0 20px black;
}
注意上面的逗号。
聪明的你一定想到了,在 css 中有两种分割方法,一个是使用空格 进行分割,而另一种方式就是上面所示的使用逗号进行分割。
下面展示如何使用空格进行分割。其实就是将 +
变成 +_
即可:
那么,问题来了 ,如果我多次使用合并属性,并且每次或用 +
或用 +_
这个时候又如何?
- 这个时候只看最后一次合并属性用的是
+
还是+_
示例:
less
.button {
.border-radius(5px);
.box-shadow(0 0 10px rgba(0, 0, 0, .5));
padding: 10px;
background-color: blue;
color: white;
}
.button-special {
.button(); // 继承 .button 的样式
background-color: red; // 覆盖背景颜色
border: 2px solid green; // 添加新的边框样式
}
// 假设我们想要合并两个具有相同属性的样式规则
.merged-styles {
.button-special(); // 继承 .button-special 的样式,包括 background-color 和 border
border: 3px dashed orange, 2px solid green; // 合并 border 属性,Less 会自动处理
}
// 生成的 CSS 将是:
// .merged-styles {
// border-radius: 5px;
// box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
// padding: 10px;
// color: white;
// background-color: red;
// border: 3px dashed orange, 2px solid green; // 合并后的 border 属性
// }