## 入门

### 介绍

Less(Leaner Style Sheets 的缩写)是一门向后兼容的 `CSS` 扩展语言

- CSS 备忘清单 (jaywcjlove.github.io)
- 在线编译预览 (lesscss.org)

在 Node.js 环境中使用 `Less`

    $ npm install -g less
    $ lessc styles.less styles.css

在浏览器环境中使用 `Less`

    <link rel="stylesheet/less" type="text/css" href="styles.less" />
    <script src="https://cdn.jsdelivr.net/npm/less@4" ></script>

### 变量(Variables)

    @width: 10px;
    @height: @width + 10px;

    #header {
      width: @width;
      height: @height;
    }

编译 css 为：

    #header {
      width: 10px;
      height: 20px;
    }

另见: 变量的更多信息

### 混合(Mixins)

    .bordered {
      border-top: dotted 1px black;
      border-bottom: solid 2px black;
    }

    #menu a {
      color: #111;
      .bordered();
    }

    .post a {
      color: red;
      .bordered();
    }

另见: 混合(Mixin)的更多信息

### 嵌套(Nesting)

    #header {
      color: black;
    }
    #header .navigation {
      font-size: 12px;
    }
    #header .logo {
      width: 300px;
    }

👇👇 更改为 less 的写法 ✅ 👇👇

    #header {
      color: black;
      .navigation {
        font-size: 12px;
      }
      .logo {
        width: 300px;
      }
    }

### 父选择器 &

    .button {
      color: blue;
      &-ok {
        background-image: url("ok.png");
      }
      &:hover {
        color: green;
      }
    }

编译 css 为：

    .button {
      color: blue;
    }
    .button-ok {
      background-image: url("ok.png");
    }
    .button:hover {
      color: green;
    }

### @规则嵌套和冒泡

    .component {
      width: 300px;
      @media (min-width: 768px) {
        width: 600px;
        @media  (min-resolution: 192dpi) {
          background-image: url(/img/icon2x.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/icon2x.png);
      }
    }
    @media (min-width: 1280px) {
      .component {
        width: 800px;
      }
    }

### 运算(Operations)

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

    @conversion-1: 5cm + 10mm; // 结果是 6cm
    @conversion-2: 2 - 3cm - 5mm; // 结果 -1.5cm
    @incompatible-units: 2 + 5px - 3cm;
    // 结果是 4px
    @base: 5%;
    @filler: @base * 2; // 结果是 10%
    @other: @base + @filler; // 结果是 15%

    @base: 2cm * 3mm; // 结果是 6cm
    @color: (#224488 / 2); // 结果是 #112244
    background-color: #112244 + #111;
    // 结果是 #223355
    @color: #222 / 2;
    // 结果是 `#222 / 2`, not #111
    background-color: (#FFFFFF / 16);
    // 结果是 #101010

#### calc() 特例

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

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

### 转义(Escaping)

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

编译 css 为：

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

从 Less 3.5 开始，可以简写为

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

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

### 函数(Functions)

    @base: #f04615;
    @width: 0.5;

    .class {
      width: percentage(@width); // 返回 `50%`
      color: saturate(@base, 5%);
      background-color:
          spin(lighten(@base, 25%), 8);
    }

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

### 命名空间和访问符

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

把 `.button` 类混合到 `#header a` 中，我们可以这样做

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

### 映射(Maps)

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

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

输出符合预期(css)：

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

另见：映射(Maps)

### 作用域（Scope）

    @var: red;

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

和上面实例代码相同

    @var: red;

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

另见：懒加载

### 注释（Comments）

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

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

块注释和行注释都可以使用

### 导入（Importing）

    @import "library"; // library.less
    @import "typo.css";

另见：导入(Importing)的知识

### Extend

    nav ul {
      &:extend(.inline);
      background: blue;
    }
    .inline {
      color: red;
    }

编译 css 为：

    nav ul {
      background: blue;
    }
    .inline,
    nav ul {
      color: red;
    }

## 函数

### 逻辑函数 if & boolean

    @bg: black;
    @bg-light: boolean(luma(@bg) > 50%);

    div {
      background: @bg;
      color: if(@bg-light, black, white);
    }

编译 css 为：

    div {
      background: black;
      color: white;
    }

### 字符串函数

:- | :-
--- | ---
`escape` | 将 URL 编码应用于输入字符串中的特殊字符
`e` | 字符串转义
`%` | 第一个参数是带有占位符的字符串

    escape('a=1') // 输出 a%3D1

    @mscode: "ms:alwaysHasItsOwnSyntax.For.Stuff()"
    filter: e(@mscode);
    // 输出 filter: ms:alwaysHasItsOwnSyntax.For.Stuff();

    format-a-d: %("repetitions: %a file: %d", 1 + 2, "directory/file.less");
    // 输出 format-a-d: "repetitions: 3 file: "directory/file.less"";

### 替换字符串 replace

    replace("Hello, Mars?", "Mars\?", "Earth!");
    replace("One + one = 4", "one", "2", "gi");
    replace('This is a string.', "(string)\.$", "new $1.");
    replace(~"bar-1", '1', '2');

预期输出

    "Hello, Earth!";
    "2 + 2 = 4";
    'This is a new string.';
    bar-2;

### length

    @list: "banana", "tomato", "potato", "peach";
    n: length(@list);

预期输出

    n: 4;

返回值列表中的元素数

### extract

    @list: apple, pear, coconut, orange;
    value: extract(@list, 3);

预期输出

    value: coconut;

返回列表中指定位置的值

### range

    value: range(4);
    // 输出 value: 1 2 3 4;
    value: range(10px, 30px, 10);
    // 输出 value: 10px 20px 30px;

生成跨越一系列值的列表

### each

    @selectors: blue, green, red;

    each(@selectors, {
      .sel-@{value} {
        a: b;
      }
    });

预期输出

    .sel-blue {
      a: b;
    }
    .sel-green {
      a: b;
    }
    .sel-red {
      a: b;
    }

每个列表成员的每个规则集都绑定到 `@value`、`@key` 和 `@index` 变量

    @set: {
      one: blue;
      two: green;
      three: red;
    }
    .set {
      each(@set, {
        @{key}-@{index}: @value;
      });
    }

预期输出

    .set {
      one-1: blue;
      two-2: green;
      three-3: red;
    }

将规则集的评估绑定到列表的每个成员

### each()

    set-2() {
      one: blue;
      two: green;
      three: red;
    }
    .set-2 {
      // 调用 mixin 并迭代每个规则
      each(.set-2(), .(@v, @k, @i) {
        @{k}-@{i}: @v;
      });
    }

预期输出

    .set-2 {
      one-1: blue;
      two-2: green;
      three-3: red;
    }

### 使用 `range` 和 `each` 创建一个 `for` 循环

    each(range(4), {
      .col-@{value} {
        height: (@value * 50px);
      }
    });

预期输出

    .col-1 {
      height: 50px;
    }
    .col-2 {
      height: 100px;
    }
    .col-3 {
      height: 150px;
    }
    .col-4 {
      height: 200px;
    }

### 数学函数

:- | :-
--- | ---
`ceil(2.4)` (输出 3) | 向上舍入到下一个最大整数 #
`floor(2.6)` (输出 2) | 向下舍入到下一个最小整数 #
`percentage(0.5)` (输出 50%) | 将浮点数转换为百分比字符串 #
`round(1.67)` (输出 2) | 应用舍入 #
`sqrt(25cm)` (输出 5cm) | 计算数字的平方根。保持单位不变 #
`abs(25cm)` (输出 25cm) | 计算数字的绝对值。 保持单位不变 #
`sin(1deg)` (输出 0.01745240643728351) | 计算正弦函数 #
`asin(-0.8414709848078965)` (输出 -1rad) | 计算反正弦（正弦的倒数）函数 #
`cos(1deg)` (输出 0.9998476951563913) | 计算余弦函数 #
`acos(0.5403023058681398)` (输出 1rad) | 计算反余弦（余弦的倒数）函数 #
`tan(1deg)` (输出 0.017455064928217585) | 计算正切函数 #
`atan(-1.5574077246549023)` (输出 -1rad) | 计算反正切（正切的倒数）函数 #
`pi()` (输出 3.141592653589793) | π (pi) #
`pow(0cm, 0px)` (输出 1cm) | 返回第一个参数的第二个参数次幂的值 #
`mod(11cm, 6px)` (输出 5cm) | 返回第一个参数模数第二个参数的值 #
`min(5, 10)` (输出 5) | 返回一个或多个值中的最小值 #
`max(5, 10)` (输出 10) | 返回一个或多个值中的最大值 #

### 颜色定义函数

:- | :-
--- | ---
`rgb` | #
`rgba` | #
`argb` | #
`hsl` | #
`hsla` | #
`hsv` | #
`hsva` | #

### 类型函数

:- | :-
--- | ---
`isnumber` | 值是否为数字 #
`isstring` | 值是否为字符串 #
`iscolor` | 值是否为颜色值 #
`iskeyword` | 值是否为 keyword #
`isurl` | 值是否为 url 值 #
`ispixel` | 值是否为像素值 #
`isem` | 值是否为 em 值 #
`ispercentage` | 值是否为 百分百 值 #
`isunit` | 值是是否为指定单位的数字 #
`isruleset` | 值是否为规则集 #
`isdefined` | 值是否为 defined #

### 杂项函数

:- | :-
--- | ---
`color` | #
`image-size` | #
`image-width` | #
`image-height` | #
`convert` | #
`data-uri` | #
`default` | #
`unit` | #
`get-unit` | #
`svg-gradient` | #

### 颜色通道函数

:- | :-
--- | ---
`hue` | #
`saturation` | #
`lightness` | #
`hsvhue` | #
`hsvsaturation` | #
`hsvvalue` | #
`red` | #
`green` | #
`blue` | #
`alpha` | #
`luma` | #
`luminance` | #

### 色彩运算函数

:- | :-
--- | ---
`saturate` | #
`desaturate` | #
`lighten` | #
`darken` | #
`fadein` | #
`fadeout` | #
`fade` | #
`spin` | #
`mix` | #
`tint` | #
`shade` | #
`greyscale` | #
`contrast` | #

### 颜色混合功能

:- | :-
--- | ---
`multiply` | #
`screen` | #
`overlay` | #
`softlight` | #
`hardlight` | #
`difference` | #
`exclusion` | #
`average` | #
`negation` | #

## 另见

- Less.js 官网 (lesscss.org)
- CSS 备忘清单 (jaywcjlove.github.io)
- Stylus 备忘清单 (jaywcjlove.github.io)
- 在线编译预览 (lesscss.org)