【Less】语法

2021/09/09 09:29:13

变量

变量通过 @ 定义, 变量有类似预编译的过程, 无需在使用前声明, 多次定义时以后定义的为准, 沿作用域向上寻找

定义

@link-color: #428bca;

使用

属性值

  1. 属性值: 当做属性值使用时直接引用@color: #fff, color: @color
  2. 可使用运算符计算: background: @color + #111;

插值

用作插值时需要通过 @{} 的形式引入

  1. 选择器: @className: wrapper, .@{className} {}

  2. 地址: @img: '../img', background: url('@{img}/bg.png')

  3. 导入文件路径: @themes: '../src', @import '@{themes}/index.less'

  4. 属性名: @property: color, * { @{property}: @fff; }

  5. 变量名:

    // less 语句
    @fnord: "I am fnord.";
    @var: "fnord";
    content: @@var;
    
    // 输出
    content: "i am fnord";
    

延伸(extend)

给当前选择器适配对应选择器的规则集, 将当前选择器添加到以定义的规则集中, 而不是引用扩展, 也就是把目标选择器(严格)下的规则继承到当前选择器上

语法

扩展必须在选择器的最后一个 a:hover:extend(div b).nth-child(odd), 这是不允许的 扩展是严格匹配的, 没有定义的选择器无法被扩展, 选择器 link:hover:visitedlink:visited:hover匹配相同的元素集,但 extend 将它们视为不同的元素 无法匹配带有变量的选择器

  1. 放到选择器上, 以伪类形式使用 .a:extend(.b) {}

  2. 放到规则集中, .a { &:extend(.b) }

    // less语句
    .a {
      color: red;
    }
    .b {
      border: solid;
      &:extend(.a); // 当前选择器适配 .a 的样式
    }
    .c {
      background-color: green;
      &:extend(.b);
    }
    // 输出
    
    .a,
    .b,
    .c {
      color: red;
    }
    .b.c {
      border: solid;
    }
    .c {
      background-color: green;
    }
    
  3. 允许多个扩展, 用逗号分隔, .a { &:extend(.b, .c) }.a { &:extend(.b):extend(.c) }

  4. 能够匹配嵌套的复杂选择器, 如: a:hover:extend(div b), 但是必须定义以 div b 为选择器的规则集

  5. 扩展全部(搜索并替换), 在参数的最后指定 all 关键字时, 效果等同于将当前选择器替换到对应位置

    // less语句
    .a.b.test,
    .test.c {
      color: orange;
    }
    .test {
      &:hover {
        color: green;
      }
    }
    
    .replacement:extend(.test all) {
    }
    
    // 输出
    .a.b.test,
    .test.c,
    .a.b.replacement,
    .replacement.c {
      color: orange;
    }
    .test:hover,
    .replacement:hover {
      color: green;
    }
    
  6. @media 中进行扩展时只与统一媒体声明内的选择器匹配

用例

  1. 避免添加基类, 如果有一系列元素需要统一样式并且拥有自己的样式, 就可以用 extend 将统一样式扩展到独特元素上, 而不是在 html 中通过添加相同的 class 来实现
  2. 替代混入, 对于需要统一样式的元素来说, 不需要先定义一个混入规则集再一一添加进去, 只需要定义一个选择器的规则集, 其他选择器扩展这个规则集就行

混入(mixin)

调用 mixin 时, 括号是可选的 创建 mixin 但又不想输出改 minxin 时, 可以在定义时的选择器后加括号 mixin 中的内容都会被加入到被调用的地方

定义

  1. 混合使用类选择器和 id 选择器

    // less语句
    .a,
    #b {
      color: red;
    }
    .mixin-class {
      .a();
    }
    .mixin-id {
      #b();
    }
    // 输出
    .a,
    #b {
      color: red;
    }
    .mixin-class {
      color: red;
    }
    .mixin-id {
      color: red;
    }
    
  2. 在混入后使用 !important 关键字会将其继承的所有属性标记为 !important, .a { .mix2(#000) !important }

命名空间

```less
#outer {
	.inner {
		color: red;
	}
}

.c {
	#outer > .inner;
}
```

参数混入

  1. 接收参数

    .mix1(@bg) {
      // 定义变量名
      background: @bg;
    }
    .min2(@bg:#333) {
      // 设置默认值
      background: @bg;
    }
    .mix3(@bg,@color) {
    }
    .mix4(@border, @type, @color) {
      border: @arguments; // @arguments 在 mixin 中是特殊变量, 包含调用 mixin 时传递的所有参数
    }
    .mix5(@a; @rest...) {
      // 用 ... 来定义可接收多个参数
      // @rest is bound to arguments after @a
      // @arguments is bound to all arguments
    }
    .a {
      .mix2(#000); // 如果定义了参数会覆盖默认值
      .mix3(
        #987,
        #eee; 1 1
      ); // 多个参数可以用分号或逗号分隔(不能混用), 使用分号进行分隔时可以接收以逗号分隔的参数列表,
      .mix3(
        @color:#333,
        3
      ); // 参数可以通过名称传入, 其他未命名的参数在传入后会按照顺序接收(不包括命名参数), 数量必须与定义时一致
      .mix4(1px; solid; #000);
    }
    
  2. 模式匹配, 根据参数不同更改混入的行为

    // less 语句
    @switch: light;
    .mixin(dark; @color) {
      color: darken(@color, 10%);
    }
    
    .mixin(light; @color) {
      color: lighten(@color, 10%);
    }
    
    .mixin(@_; @color) {
      // 匹配所有模式
      display: block;
    }
    
    .class {
      .mixin(@switch; #888); // 匹配对应的混入对象
      // .mixin(light; #888); // 直接写入对应类型也可以
    }
    
    // 输出
    
    .class {
      color: #a2a2a2;
      display: block;
    }
    

函数式调用

混入中定义的变量在混入后是可见的, 可以在调用者的作用域中使用(调用作用域定义同名变量时不会被混入变量覆盖), 因此可以让混入对象对参数做一些处理, 以达到封装功能的效果

```less
.average(@x, @y) { // 接收两个参数
	@average: ((@x + @y) / 2); // 处理参数并定义为变量

	.mix1() {  // 在 mixin 中定义的 mixin 也会被定义在调用者作用域中(注意不加括号的话会直接添加到css中)
		color: red;
	}
}

@average: 50px; // 父级作用域中定义的同名变量会被覆盖

div {
	.average(16px, 50px);
	padding: @average;    // 使用混入对象中定义的变量
	// @average: 100px; // 如果当前作用域中有同名变量, 以作用域中定义的为准
}
```

条件混入

受保护的 mixin, 类似于 @media 的条件查询语句, 条件可以写在定义混入或引用混入的后面

```less
	@mode:1;
	@arg: 1;
	// 定义混入时限定条件
	.a() when(@mode=1) { // 在@mode等于1的时候才允许被混入
		background: #fff;
	}
	.a() when(default()) { // 调用时所有条件都不符合时引用该样式, 类似于 default / else
		color: red;
	}
	.b {
		.a() when (@mode>=1); // 可以使用逻辑运算符
		.a() when (@mode=1) and (@arg=2); // 用 and 连接条件, 相当于 &&
		.a() when (@mode=1), (@arg=2); // 用逗号模拟 or , 相当于 ||
		.a() when not (@mode=1); // 用 not 关键字来否定条件
	}

```
  1. 类型检查函数: iscolor()isnumber()isstring()iskeyword()isurl()

  2. 检查值是否是数字, 是否使用特定单位 ispixel()ispercentage()isem()isunit()

  3. 递归调用

    // less语句
    .generate-columns(@n, @i: 1) when (@i =< @n) {
      .column-@{i} {
        width: (@i * 100% / @n);
      }
      .generate-columns(@n, (@i + 1));
    }
    .generate-columns(4);
    
    // 输出
    
    .column-1 {
      width: 25%;
    }
    .column-2 {
      width: 50%;
    }
    .column-3 {
      width: 75%;
    }
    .column-4 {
      width: 100%;
    }
    

合并

合并功能允许将多个属性中的值聚合到单个属性下的逗号或空格分隔的属性列表中, 对于背景和变换等属性很有用

```less
.mixin() {
	box-shadow+: inset 0 0 10px #555; // 属性名后面带+, 编译后属性值通过逗号连接
	background+_: url('./img/bg.png'); // 属性名后带+_, 编译后属性值通过空格连接
}

.myclass {
	.mixin();
	box-shadow+: 0 0 20px black; // 逗号连接
	background+_:100%; // 空格连接
}
```

导入(import)

  1. @import (keyword) 'filename' 注意@importkeyword 之间的空格
  2. 一个@import 语句只能导入一个文件
  3. 可以在混入中使用 @import

选项(keyword)

使用多个关键字时用逗号分隔

  1. reference:使用较少的文件,但不输出
  2. inline:在输出中包含源文件,但不对其进行处理
  3. less:无论文件扩展名是什么,都将其视为少文件
  4. css:无论文件扩展名为什么,都将其视为 CSS 文件
  5. once:仅包含一次文件(这是默认行为)
  6. multiple:多次包含文件
  7. optional:找不到文件时继续编译

父级选择器(&)

& 在选择器中可以出现多次, 可以重复引用父选择器而无需重复其名称 & 代表的是所有父级选择器累加下来的选择器, 而不是最近的祖先 可以把 & 写在其他选择器后面达成特殊样式的效果 .no-data & 在逗号分隔的多个选择器中多次使用 &;

```less
// less语句
p, a, ul, li {
	border-top: 2px dotted #366;
	& + & {  // 将会扩展为所有可能的组合
		border-top: 0;
	}
}

// 输出
p,
a,
ul,
li {
	border-top: 2px dotted #366;
}
p + p,
p + a,
p + ul,
p + li,
a + p,
a + a,
a + ul,
a + li,
ul + p,
ul + a,
ul + ul,
ul + li,
li + p,
li + a,
li + ul,
li + li {
	border-top: 0;
}
```