Skip to content

Less 预处理器

一、是什么

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

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

二、编译 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, @height800px) {
    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

js
// @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
@import "library"; // library.less
@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

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

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()的形式来调用这个混合。这就像是在访问一个命名空间内的成员。在这个例子中,#header a 选择器中调用了 #bundle.button() 混合,所以 #header a 会获得 .button 混合定义的所有样式。

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

注意,也可以使用 #bundle > .button 的形式来调用混合,这和 #bundle.button() 是等价的。

11. 映射(Maps)

用途:组织和使用值。

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

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

然后,就可以在其他地方通过 #colors[primary] 的形式来访问这个混合内的变量。这就像是在访问一个映射的键值对。在这个例子中,.button 选择器中访问了 #colors[primary]#colors[secondary],所以 .buttoncolorborder 会获得这两个变量的值。

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

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

编译为:

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

四、其他

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

Updated at:

Released under the MIT License.