Skip to content

Less 预处理器

一、是什么

Less 是一种动态样式语言,属于 CSS 预处理语言的一种。它使用类似 CSS 的语法,为 CSS 赋予了动态语言的特性,如变量、继承、运算、函数等,更方便 CSS 的编写和维护。

Less(Less 编辑器)是开源的,其第一个版本由 Ruby 写成,但在后续的版本当中,Ruby 逐渐被替换为 JavaScript。受益于 JavaScript,LESS 可以在客户端上运行(IE6+、Webkit、Firefox),也可以在服务端运行(Node.js、Rhino)。

官方文档

Less 的官方网站:lesscss.org

Less 也有非常完善的中文文档网站(由 BootCSS 团队维护):less.bootcss.com

BootCSS 团队(中文名:Bootstrap 中文网团队)是中国前端圈非常知名的一个技术社区和翻译团队。除了翻译文档,他们最广为人知的产品是 BootCDN

二、编译 less

1. 使用 less.js 编译 less

html
<style type="text/less">
  @fcolor: #900;
  @bcolor: #099;
  @len: 1000px;

  #box {
    width: @len;
    height: (@len/4);
    color: @fcolor;
    background: @bcolor;
    padding: 20px;
  }
</style>

<script src="./less.js"></script>

2. VSCode 插件自动编译 less

1)vscode 安装扩展 "Easy Less"。

2)创建扩展名是 .less 的文件,在文件中写 less 代码; Easy Less 会自动编译成同名的 CSS; 每次保存都会自动编译。

3)html 中使用 link 引入 css 文件。

3. 第三方编译工具 koala

koala (考拉) 官网:http://koala-app.com/index-zh.html

4. nodejs

安装

bash
npm install less -g

使用

bash
lessc bootstrap.less bootstrap.css

三、语法

1. 注释(Comments)

less
/* 一个块注释
 * style comment!
 */
@var: red;

// 这一行被注释掉了!
@var: white;

// 不会编译到 CSS 文件中。/**/ 会编译到 CSS 中。

2. 变量(Variables)

① 定义变量

定义变量的一般形式

less
@变量名:;

// 例子
@len: 600px;
@master-red: #900;
@prop:background-position;

如果变量的值有特殊符号

less
@变量名:~"值";

// 例子
@min768: ~"min-width:768px";
@sel01: ~".news li";

② 使用变量

将变量作为属性值使用(大部分应用场景)

less
// 直接使用 @变量名
width: @len;
color: @master-green;
background: @master-red;
border: 1px solid @master-green;

@media (@min768) {
  .container {
    width: 100%;
  }
}

将变量作为属性名或者选择器使用

less
// @{变量名}

.box {
  // 变量作为属性名
  @{prop}: 10px 10px;
}

// 变量名作为选择器
@{sel01} {
  width: @len;
  height: (@len/2);
}

less 中,变量名没有命名规范。

3. 混合(Mixin)

混合(Mixin)是一种将一组属性从一个规则集包含(或混入)到另一个规则集的方法。类似于 JavaScript 中的函数。目的是提高代码的重用性。

在 Less 中,可以使用类(class)或者ID(#ids)作为 mixin(混合)。

基本使用

less
// 在 less 中,这个既是类选择器,也是混合
.bordered {
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}
less
#menu a {
  color: #111;
  // 当作混合使用
  .bordered();
}

.post a {
  color: red;
  // 当作混合使用
  .bordered();
}

.bordered 类所包含的属性就将同时出现在 #menu a.post a 中了。

这种缺点是 .bordered 也会在 CSS 中以类选择器出现。比较合理的是在混合后面加上括号。

① 混合

定义混合

less
.center-box01() {
  position: absolute;
  width: 400px;
  height: 300px;
  left: 50%;
  top: 50%;
  margin-left: -200px;
  margin-top: -150px;
}

使用混合

less
.item {
  // 调用混合
  .center-box01();
}

.news li {
  // 调用混合
  .center-box01();
  // 其他样式
  background: #900;
  border: 1px solid #999;
}

② 带参数的混合

定义带参数的混合

less
// 定义混合 (有参数)
.center-box02(@width, @height) {
  position: absolute;
  width: @width;
  height: @height;
  left: 50%;
  top: 50%;
  margin-left: -(@width/2);
  margin-top: -(@height/2);
}

使用有参数的混合

js
// 调用有参数的混合 按照顺序传参数
.center-box02(600px,500px);

// 调用有参数的混合 按照名字传参
.center-box02(@height:600px, @width:700px);

③ 参数有默认值的混合

less
// 定义混合 参数设置默认值
// 有默认值的参数在后面
// 可以按照顺序传参,也可以按照名字传参
.center-box03(@width, @height:800px) {
  position: absolute;
  width: @width;
  height: @height;
  left: 50%;
  top: 50%;
  margin-left: -(@width/2);
  margin-top: -(@height/2);
}

// 有默认值的参数在前面后面都可以
// 只能按照名字传参
.center-box04(@width:1200px, @height) {
  position: absolute;
  width: @width;
  height: @height;
  left: 50%;
  top: 50%;
  margin-left: -(@width/2);
  margin-top: -(@height/2);
}

④ @arguments

less
// @arguments 获取参数列表
.box-shadow(@x, @y, @b, @o, @color) {
  -webkit-box-shadow: @arguments;
  -moz-box-shadow: @arguments;
  -o-box-shadow: @arguments;
  box-shadow: @arguments;
}

.box {
  width: 400px;
  height: 300px;
  background: #900;
  .box-shadow(3px, 10px, 15px, 0px, #ccc);
}

4. Less 条件判断

less
.triangle(@border-width, @color, @direction) when (@direction=up) {
  width: 0;
  height: 0;
  border-style: solid;
  border-width: @border-width;
  border-color: transparent transparent @color transparent;
}

.triangle(@border-width, @color, @direction) when (@direction=down) {
  width: 0;
  height: 0;
  border-style: solid;
  border-width: @border-width;
  border-color: @color transparent transparent transparent;
}
 
.triangle(@border-width, @color, @direction) when (@direction=left) {
  width: 0;
  height: 0;
  border-style: solid;
  border-width: @border-width;
  border-color: transparent @color transparent transparent;
}

.triangle(@border-width, @color, @direction) when (@direction=right) {
  width: 0;
  height: 0;
  border-style: solid;
  border-width: @border-width;
  border-color: transparent transparent transparent @color;
}

5. 导入(Importing)

“导入”的工作方式和你预期的一样。你可以导入一个 .less 文件,此文件中的所有变量就可以全部使用了。如果导入的文件是 .less 扩展名,则可以将扩展名省略掉:

less
// index.css 内容

@import "library"; // 其实导入的文件是 library.less。会编译之后把内容引入到 index.css
@import "typo.css"; // 编译后还是 @import "typo.css";

6. 嵌套(Nesting)

Less 提供了使用嵌套(nesting)代替层叠或与层叠结合使用的能力。

① 基本使用 (层级选择器)

less
.news {
  li {}
  >li {}
  +li {}
  ~li {}
}

编译为:

css
.news {}
.news li {}
.news > li {}
.news + li {}
.news ~ li {}

② & 符号应用 (交集选择器组合)

& 代表所有父选择器(不仅仅是最近的祖级)。

less
.item {
  &:hover {}
  &.active {}
}

编译为:

css
.item {}
.item:hover {}
.item.active {}

③ 媒体查询的嵌套

@规则嵌套和冒泡

@ 规则(例如 @media@supports)可以与选择器以相同的方式进行嵌套。@ 规则会被放在前面,同一规则集中的其它元素的相对顺序保持不变。这叫做冒泡(bubbling)。

less
.component {
  width: 300px;
  @media (min-width: 768px) {
    width: 600px;
    @media (min-resolution: 192dpi) {
      background-image: url(/img/retina2x.png);
    }
  }
  @media (min-width: 1280px) {
    width: 800px;
  }
}

编译为:

css
.component {
  width: 300px;
}
@media (min-width: 768px) {
  .component {
    width: 600px;
  }
}
@media (min-width: 768px) and (min-resolution: 192dpi) {
  .component {
    background-image: url(/img/retina2x.png);
  }
}
@media (min-width: 1280px) {
  .component {
    width: 800px;
  }
}

④ 混合和嵌套结合

可以将伪选择器(pseudo-selectors)与混合(mixins)一同使用。下面是一个经典的 clearfix 技巧,重写为一个混合(mixin)。

less
.clearfix() {
  &::after {
    content: "";
    display: block;
    clear:both;
  }
}

7. 运算(Operations)

① 算术运算符

算术运算符 +-*/ 可以对任何数字、颜色或变量进行运算。

如果可能的话,算术运算符在加、减或比较之前会进行单位换算。计算的结果以最左侧操作数的单位类型为准。如果单位换算无效或失去意义,则还是以最左侧操作数的单位类型为准。无效的单位换算例如:px 到 cm 或 rad 到 % 的转换。

如果两个操作数单位不一致,结果使用第一个操作数的单位;如果只有一个操作数有单位,结果就使用该单位。

注意:除运算需要使用小括号。

less
// 所有操作数被转换成相同的单位
@conversion-1: 5cm + 10mm; // 结果是 6cm
@conversion-2: 2 - 3cm - 5mm; // 结果是 -1.5cm

// conversion is impossible
@incompatible-units: 2 + 5px - 3cm; // 4px

// example with variables
@base: 5%;
@filler: @base * 2; // 结果是 10%
@other: @base + @filler; // 结果是 15%

乘法和除法不作转换。因为这两种运算在大多数情况下都没有意义,一个长度乘以一个长度就得到一个区域,而 CSS 是不支持指定区域的。Less 将按数字的原样进行操作,并将为计算结果指定明确的单位类型。

less
@base: 2cm * 3mm; // 结果是 6cm

你还可以对颜色进行算术运算:

less
@color: (#224488 / 2); // 结果是 #112244
background-color: #112244 + #111; // 结果是 #223355

Less 4.0+ 开始,除法必须加括号!

  • 如果不加括号,/ 会被当作 CSS 的分隔符(比如 font: 16px/20px 表示字号/行高),不会进行计算。

  • 例子对比

    @color: #222 / 2; ➡️ 结果原样输出字符串 #222 / 2(没算)。

    background-color: (#FFFFFF / 16); ➡️ 结果是 #101010(算了,因为加了括号)。

② calc() 特例

为了与 CSS 保持兼容,calc() 并不对数学表达式进行计算,但是在嵌套函数中会计算变量和数学公式的值。

less
@var: 50vh/2;
width: calc(50% + (@var - 20px));  // 结果是 calc(50% + (25vh - 20px))

8. 函数(Functions)

Less 内置了多种函数用于转换颜色、处理字符串、算术运算等。

percentage()		计算百分比
mod()				取余运算
lighten()			颜色调高亮度
darken()			颜色调低亮度

函数的用法非常简单。下面这个例子将介绍如何利用 percentage 函数将 0.5 转换为 50%,将颜色饱和度增加 5%,以及颜色亮度提高 25% 并且色相值增加 8:

less
@base: #f04615;
@width: 0.5;

.class {
  // percentage(@width) 返回的是 50%,即.class的宽度为 50%。
  width: percentage(@width);
  // saturate(@base, 5%) 会将 @base 颜色的饱和度提高 5%。所以,这会使得原本的红色变得更鲜艳一些。
  color: saturate(@base, 5%);
  /* 
    lighten(@base, 25%) 会将 @base 颜色的亮度提高 25%,
    然后 spin() 函数会将这个亮度提高后的颜色在色轮上旋转 8 度。
    这样,背景色就会是一个比原红色更亮且稍微偏向其他颜色的新颜色。
  */
  background-color: spin(lighten(@base, 25%), 8);
}

官方函数文档:https://less.bootcss.com/functions

9. 转义(Escaping)

转义(Escaping)允许你使用任意字符串作为属性或变量值。任何 ~"anything"~'anything' 形式的内容都将按原样输出,除非 interpolation

less
@min768: ~"(min-width: 768px)";

.element {
  @media @min768 {
    font-size: 1.2rem;
  }
}

编译为:

css
@media (min-width: 768px) {
  .element {
    font-size: 1.2rem;
  }
}

注意,从 Less 3.5 开始,可以简写为:

less
@min768: (min-width: 768px);

.element {
  @media @min768 {
    font-size: 1.2rem;
  }
}

在 Less 3.5+ 版本中,许多以前需要“引号转义”的情况就不再需要了。

interpolation 是什么?

在 Less 中,插值(Interpolation)是一种特性,允许你在字符串中嵌入变量,并在运行时将这些变量替换为它们的值。

插值的语法是 @{variableName},其中 variableName 是你要插入的变量的名称。当 Less 解析这个字符串时,它会找到所有的插值表达式,并用相应的变量值替换它们。

less
@myColor: 'red';

.myClass {
  color: ~"@{myColor}";
}

在这个例子中,~"@{myColor}" 是一个插值表达式。当 Less 解析这个表达式时,它会找到 @{myColor},并用 @myColor 变量的值(即 'red')替换它。所以,生成的 CSS 代码是:

css
.myClass {
  color: red;
}

上面解释了就算你使用了转义语法,但如果里面的内容是 interpolation,还是会被替换,不会原样输出。interpolation 更常见的用法如下:

less
/* 选择器上 */
@my-selector: banner;
.@{my-selector} {
  font-weight: bold;
}

/* URL 路径中 */
@images: "../img";
body {
  background: url("@{images}/white-sand.png");
}

/* 属性名上 */
@property: color;
.widget {
  @{property}: #0ee;
  background-@{property}: #999;
}

10. 命名空间和访问符

用途:组织和重用代码。

在 Less 中,可以创建一个命名空间,然后在这个命名空间内定义一些混合(mixin)或者选择器。在这个例子中,#bundle() 就是一个命名空间,它内部定义了 .button.tab.citation 三个混合。

less
#bundle() {
  .button {
    display: block;
    border: 1px solid black;
    background-color: grey;
    &:hover {
      background-color: white;
    }
  }
  .tab { ... }
  .citation { ... }
}

然后,就可以在其他地方通过#bundle.button()的形式来调用这个混合。这就像是在访问一个命名空间内的成员。

less
#header a {
  color: orange;
  #bundle.button();  // 还可以书写为 #bundle > .button 形式
}

在这个例子中,#header a 选择器中调用了 #bundle.button() 混合,所以 #header a 会获得 .button 混合定义的所有样式。

11. 映射(Maps)

用途:组织和使用值。

从 Less 3.5 版本开始,还可以将混合(mixins)和规则集(rulesets)作为一组值的映射(map)使用。

在 Less 中,可以创建一个混合(mixin),然后在这个混合内定义一些变量。在这个例子中,#colors() 就是一个混合,它内部定义了 primary 和 secondary` 两个变量。

less
#colors() {
  primary: blue;
  secondary: green;
}

.button {
  color: #colors[primary];
  border: 1px solid #colors[secondary];
}

然后,就可以在其他地方通过 #colors[primary] 的形式来访问这个混合内的变量。这就像是在访问一个映射的键值对。

编译为:

css
.button {
  color: blue;
  border: 1px solid green;
}

在这个例子中,.button 选择器中访问了 #colors[primary]#colors[secondary],所以 .buttoncolorborder 会获得这两个变量的值。

四、其他

1. 作用域(Scope)

Less 中的作用域。首先在本地查找变量和混合(mixins),如果找不到,则从“父”级作用域继承。

less
@var: red;

#page {
  @var: white;
  #header {
    color: @var; // white
  }
}

注意:混合(mixin)和变量的定义不必在引用之前事先定义。因此,下面的 Less 代码示例和上面的代码示例是相同的:

less
@var: red;

#page {
  #header {
    color: @var; // white
  }
  @var: white;
}
preview
图片加载中
预览

Released under the MIT License.