LESS预处理器

8/1/2022

# 一、基本介绍

# 1.1 css 预处理器的由来

​ 相信前端开发人员对与CSS(Cascading Style Sheet-级联样式表)这种「面向命名语言」,一定非常熟悉。你可能在某个舍友熟睡的深夜,还在电脑面前被 css 繁重、冗杂的样式,折磨的死去活来。

我们曾经面对 css 很多令人发指的不友好特性,也因为 css 的低复用性而刀耕火种。

css 预处理器就是这样被创造出来,弥补了直接写 css 的一些缺憾:

  • 语法不够强大,比如无法嵌套书写导致模块化开发中需要书写很多重复的选择器;
  • 没有变量和合理的样式复用机制,使得逻辑上相关的属性值必须以字面量的形式重复输出,导致难以维护。

# 1.2 什么是预处理

​ CSS 预处理器用一种专门的编程语言,进行 Web 页面样式设计,然后再编译成正常的 CSS 文件,以供项目使用。CSS 预处理器为 CSS 增加一些编程的特性,无需考虑浏览器的兼容性问题。

# 1.3 主流的预处理器

  • Sass:2007年诞生,最早也是最成熟的CSS预处理器,拥有ruby社区的支持和compass这一最强大的css框架,目前受LESS影响,已经进化到了全面兼容CSS的SCSS。ruby环境,让CSS有了更完整的逻辑和判断能力,比如支持if这些 ,基于ruby
  • Less:2009年出现,受SASS的影响较大,在ruby社区之外支持者远超过SASS,其缺点是比起SASS来,可编程功能不够,不过优点是简单和兼容CSS。著名的Twitter Bootstrap就是采用LESS做底层语言的。支持原生js,node, 让CSS有了基本的逻辑运算能力 , 基于js写的
  • Stylus:2010年产生,来自Node.js社区,主要用来给Node项目进行CSS预处理支持,在此社区之内有一定支持者,在广泛的意义上人气还完全不如SASS和LESS。 node -- VUE阶段开发项目中我们使用stylus, 这个让CSS变成跟一门编程语言类似了

# 1.3 总结

  • Sass和Less语法严谨、Stylus相对自由。因为Less长得更像CSS,所以它可能学习起来更容易。
  • Sass 和 Compass、Stylus 和 Nib 都是好基友。
  • Sass 和 Stylus 都具有类语言的逻辑方式处理:条件、循环等,而 Less 需要通过When等关键词模拟这些功能,这方面 Less 比不上 Sass 和 Stylus。
  • Less 在丰富性以及特色上都不及 Sass 和 Stylus,若不是因为 Bootstrap 引入了 Less,可能它不会像现在这样被广泛应用

# 1.4 官方网站

# 二、基本使用

# 2.1 安装less

  1. 直接引用(不推荐)

    • 在引入之前,我们需要创建一个 Less 文件,Less 文件的后缀名为 .less,所以我们可以将文件命名为 index.less

    • 然后我们就可以通过 <link> 标签向 HTML 页面中引入 index.less 文件,和引入 CSS 文件类似,但是需要将 type 属性的值修改为 text/less

      <link rel="stylesheet/less" type="text/less" href="./index.less" />
      
      1
    • 然后下载使用官方提供的 CDN 进行脚本引入

      <script src="https://cdn.bootcdn.net/ajax/libs/less.js/3.13.0/less.js"></script>
      
      1
  2. 通过NPM安装(不推荐)

  3. vscode安装(推荐)

    • 打开VSCode编辑器,安装Easy LESS插件
    • 在文件夹中新建less文件,然后保存,即可在当前文件夹中编译出相应的css文件。

# 2.2 使用方式

  • 引入js的方式

    • less

      body {
          background-color: red;
      }
      
      1
      2
      3
    • html

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
          <link rel="stylesheet" href="./index.less" type="text/less">
          <style type="text/less">
              #box{
                  width: 100px;
                  height: 100px;
                  background-color: pink;
                  .con{
                      width: 50px;
                      height: 50px;
                      background-color: green;
                  }
              }
          </style>
      </head>
      
      <body>
          <div id="box">
              <div class="con"></div>
          </div>
          <script src="https://cdn.bootcdn.net/ajax/libs/less.js/3.13.0/less.js"></script>
      </body>
      </html>
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
  • vsCode使用的方式

    • less

      body{
          background-color: aquamarine;
      }
      
      1
      2
      3
    • html

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Document</title>
          <link rel="stylesheet" href="./Untitled-1.css">
      </head>
      <body>
      </body>
      </html>
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10

# 2.3 注释

注释的适当使用可以保证代码的可读性,Less 支持两种类型的注释:多行注释和单行注释

注释使代码清晰,并允许用户轻松地理解。 您可以在代码中使用块样式和行内注释,但是当编译LESS代码时,单行注释不会显示在CSS文件中

  • less
#box{
    // 这是一个隐藏的注释
    width: 200px;
    height: 200px;
    background-color: aquamarine;
     /**
      font-size: 100px;
      我是一个可以显示的注释
    **/
}
1
2
3
4
5
6
7
8
9
10
  • css
#box {
  width: 200px;
  height: 200px;
  background-color: aquamarine;
  /**
      font-size: 100px;
      我是一个可以显示的注释
    **/
}
1
2
3
4
5
6
7
8
9

# 2.4 变量

多次重复相同的值,通常在您的样式表中可看到。不用多次使用相同的值,可以使用变量。它使代码的维护更容易,并且可以从单个位置控制这些值。

观察代码有什么问题:

#outer {
    width: 300px;
    height: 300px;
    background-color: aqua;
    margin: auto;
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
}
1
2
3
4
5
6
7
8
9
10
11
  • 变量作为样式的值使用
    • 一般使用的场景是部分重复的值和一些比较难以记忆的颜色值
@v:0;
#outer {
    width: 300px;
    height: 300px;
    background-color: aqua;
    margin: auto;
    position: absolute;
    left: @v;
    top: @v;
    bottom: @v;
    right: @v;
}
1
2
3
4
5
6
7
8
9
10
11
12
  • 变量作为变量的名字--@{变量名}
@bg : background;
#outer {
    width: 300px;
    height: 300px;
    @{bg}: aqua;
    margin: auto;
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
  • 变量作为选择器使用--@{选择器}
@o:#outer;
@{o} {
    width: 300px;
    height: 300px;
    background-color: aqua;
    margin: auto;
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
  • 变量作为url地址
@img1:'https://img2.baidu.com/it/u=2238622225,3486857165&fm=11&fmt=auto&gp=0.jpg';
@img2:url('https://img2.baidu.com/it/u=2238622225,3486857165&fm=11&fmt=auto&gp=0.jpg');
@img3:@img2;

#outer {
    width: 300px;
    height: 300px;
    background-color: aqua;
    margin: auto;
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
    // background:url(@img1) 0 0 no-repeat;
    // background: @img2 0 0 no-repeat;
    background: @img3 0 0 no-repeat;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  • 变量的计算
@v:0;
@z:@v + 2;
#outer {
    width: 300px;
    height: 300px;
    background-color: aqua;
    margin: auto;
    position: absolute;
    left: @v;
    top: @v;
    bottom: @v;
    right: @z;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
  • 变量的延迟加载-面试题
@var: 0;
.class {
    @var: 1;
    .brass {
        @var: 2;
        //less变量延迟加载,也就是等待当前样式所在区域的代码全部执行完毕,才进行加载变量
        three: @var;
        @var: 3;
    }
    one: @var;
}
1
2
3
4
5
6
7
8
9
10
11

# 2.5 嵌套

# 2.5.1 基础嵌套

​ 在使用标准CSS时,要为多层嵌套的元素定义样式,要么使用后代选择器从外到内的嵌套定义,要么给这个元素加上类名或 id 来定义。这样的写法虽然很好理解,但维护起来很不方便,因为无法清晰了解到样式之间的关系。

在Less中,嵌套规则使这个问题迎刃而解。嵌套规则允许在一个选择器中嵌套另一个选择器,这更容易设计出精简的代码,并且样式之间的关系一目了然。

body{
    background-color: red;
    .outer{
        width: 1200px;
        border: 1px solid black;

        .header{
            height: 100px;
            background-color: yellow;
        }
        .con{
            margin: 0 auto;
            border: 1px solid green;
        }
        .footer{
            width: 1200px;
            box-shadow: 0px 0px 0px 0px #ccc;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 2.5.2 父级引用

使用&:代表前边的所有父级元素,常用在伪元素 伪类 css结构类等需求上

内层选择器前面的 & 符号就表示对父选择器的引用。在一个内层选择器的前面,如果没有 & 符号,则它被解析为父选择器的后代;如果有 & 符号,它就被解析为父元素

ul{
    li{
        line-height: 40px;
        &:nth-child(1){
            line-height: 80px;
        }
    }

    li:nth-child(1){
        line-height: 80px;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
div{
    height: 100px;
    &>span{
        width: 100px;
        &>nav{
            background-color: red;
        }
    }
}
1
2
3
4
5
6
7
8
9

# 2.6 less运算

运算类型:任何数值,颜色,变量都可以运算

单位:less会给你自动推算单位,所以不需要每一个都加单位,但保证至少有一个加了单位

注意:运算符与数值之间要以空格分开,涉及优先级时以()进行优先级计算

# 2.6.1 数值型运算

header{
    width: 100px + 10;
    height: 20 + 10px;

    // height: 20 - 10px;
    // height: 20 * 10px;
    // 注意除法必须加()
    // less中做算术运算的时候一般加法+,减法-,乘法*
    // 可以直接写基本不会出现什么问题但是除法/需要()括起来,
    // 不然会认为你的是有两个值 值一 / 值二,不会进行计算返回计算结果
    // height: (20 / 10px);
}
1
2
3
4
5
6
7
8
9
10
11
12

思考:如果两个数值都有单位,那么会返回什么单位

header{
    width: 100px + 10;
    height: 20rem + 10px;
}
1
2
3
4

注意:单位加在哪里都行,只要有一个地方有单位,less就能推断出计算后结果的单位。

​ 如果两面都有单位,那么以第一个单位为主。

# 2.6.2 颜色计算

规则: less在运算时,先将颜色值转化为rgba模式,然后再转换为16进制的颜色值并返回

注意1 : 在颜色运算时,能直接使用颜色的名称如green进行运算,比如 red - 55 = #c80000,但是在之前这个功能无效

注意2 : 实际上是拆分之后再转化成16进制的 #ffffff - 55 = c8c8c8 = rgb(200,200,200),拆成两个一个,分别代表r,g,b

注意3 : 加的值超过255,只会取到255 #111111 + 260 = #ffffff

注意4 : rgb模式的取值为 0~255

header {
  color: #fff;
  color: #f5f5f5;
  background-color: #c80000;
  background-color: #ffffff;
  background-color: #373737;
}
1
2
3
4
5
6
7

# 2.6.3 变量计算

@w:20px;
header{
    width: @w + 2;
}
1
2
3
4

# 2.7 less混合

​ 混合是一种将一组属性从一个规则集包含或混入到另一个规则集的方法。简单一点来说,其实混合就有点类似编程语言中的函数,通过这种方式,可以在代码中实现复用。

# 2.7.1 普通的Mixins

.s1{
  font-size: 10px;
  color: #ccc;
}
.s2{
  font-size: 10px;
  color: #ccc;
  padding: 10px;
}
1
2
3
4
5
6
7
8
9

可以很明显的看到,.s1 样式类中的代码,.s2 样式类中也有,这里是只有两个样式类,如果有很多个选择器时,是不是就会造成很多重复的代码

混合 Mixin 就可以帮助我们来解决这个问题,实现代码的复用。使用起来也很简单,只需要在 .s2 中引用 .s1 即可

.s1 {
  font-size: 14px;
  color: #ccc;
}
.s2 {
  .s1;//注意没有加();
  padding: 10px;
}
1
2
3
4
5
6
7
8

思考:如果有很多的选择器都有类似样式,那么上面这种方式的缺点?

# 2.7.2 不输出的Mixins

我们可以看到在编译时, .s1.s2 两个样式类都被编译成了 CSS 代码,但是某些时候有可能这有可能造成重复,所以我们可能不希望 .s1 样式类本身被编译到 CSS 文件中

.s1(){
  font-size: 14px;
  color: #ccc;
}

.s2{
  .s1();
  padding: 10px;
} 
1
2
3
4
5
6
7
8
9

# 2.7.3 带参数的Mixins

在声明混合的时候,可以在小括号中声明形参。形参由@+变量名定义。调用的时候可以传入实参

如果很多的位置都需要使用某一个Mixins,而且参数还不一样的话,那么就可以使用参数的Mixins

.s1(@f,@c){
    font-size: @f;
    color: @c;
  }
.s2{
    .s1(14px,red);
    padding: 10px;
  } 
1
2
3
4
5
6
7
8

思考:如果有屌丝不想按照顺序传递参数,咋办?

# 2.7.4 参数有默认值的混合

可以直接在混合中定义形参的时候,给形参设置默认值,比如(@color:red),当使用混合的时候,如果有实参传递,则使用实参的值,否则使用形参的默认值

.s1(@f:10px,@c:red){
    font-size: @f;
    color: @c;
  }
  
.s2{
    .s1();
    padding: 10px;
} 
1
2
3
4
5
6
7
8
9

# 2.7.5 Mixins命名空间

Less 中也有命名空间的概念,命名空间用于在通用名称下对 Mixins 进行分组,使用命名空间可以避免名称冲突,并从外部封装 Mixins 组。例如可以将类选择器或者ID选择器作为一个命名空间,然后将 Mixins 放在命名空间中,这样可以避免与引入的其他文件造成冲突

.name_space{ 
    .s1(){
      font-size: 12px;
    }
  }
  .s2{
    // .name_space > .s1();  // 引用  以下哪种方式都可以
    // .name_space.s1;
    // .name_space.s1();
    // .name_space .s1;
    .name_space .s1();
  }
1
2
3
4
5
6
7
8
9
10
11
12

# 2.7.6 !important关键字

!important 关键字用于覆盖特定属性。如果我们在 Mixins 引用后面加上 !important 关键字,则会将 Mixins 中的所有属性标记为 !important

html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>important关键字</title>
        <link rel="styleSheet" type="text/css" href="./index.css">
    </head>
    <body>
        <h1>welcome to red romance!</h1>
    </body>
</html>   
1
2
3
4
5
6
7
8
9
10
11

less

.mixin(){
  color: red;
}
h1{
  color: #ccc;
  .mixin() !important;
}
1
2
3
4
5
6
7

# 2.7.7 匹配模式

在Less中尝试利用模式匹配替if/else,其执行原理类似switch/case。

因为一个混合可能有多种形式,所以Less提供了一种机制,允许根据参数的值来改变 mixin的行为。

其中当参数是@_开头的,是调用此混合必选的。

//模式匹配中,公有的样式混合 需要书写@_做为参数
.main(@_) {
    width: 100px;
    height: 100px;
}

.main(color1) {
    background-color: pink;
}

.main(color2) {
    background-color: yellow;
}

.outer {
    .main(color1)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 2.7.8 重载

相同的混合,不同的行为,可以根据调用的时候传入的实参个数选择匹配的混合内容

.main(@w) {
    width: @w;
}

.main(@w, @h) {
    width: @w;
    height: @h;
}

.outer {
    //重载:根据参数个数不同,来匹配不同的混合
    .main(100px, 100px)
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 2.7.9 守卫

根据判断条件选中Mixin的行为

类似于JavaScript的if/else,使用when语法

Guards 允许我们使用>,>=,<,<=,=,关键字true(只匹配关键字true,非true不会匹配),支持逻辑and ,not ()

同时我们可以使用“,”分割多个Guards,其表示只要其中任意一个满足就为true

案例1:

.main(@a) when(@a>30) {
    width: 100px;
    height: 100px;
}

.main(@a) when(@a<=30) {
    width: 200px;
    height: 200px;
}

.outer {
    .main(30)
}
1
2
3
4
5
6
7
8
9
10
11
12
13

案例2:

.main(@w) when(@w>1000),(@w<200) {
    width:~"@{w}px";
    height: 100px;
}

.main(@w) when(@w<=1000) and (@w>=200) {
    width:~"@{w}px";
    height: 50px;
}
.outer {
    .main(3000)
}
1
2
3
4
5
6
7
8
9
10
11
12

# 2.8 字符串插值

变量可以用类似ruby和php的方式嵌入到字符串中,通过**@{name}**这样的结构:

@h: 30;
@baseUrl: "http://redromance.vip:6666/";
.outer {
    //变量加单位,字符串拼接 再转义
    //@{h}在字符串中书写变量
    //~转义 把字符串转成css可用代码
    height:~"@{h}px";
    //字符串插值
    background: url("@{baseUrl}01.png")
}

.con {
    background: url("@{baseUrl}02.png")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 2.9 文件导入

  • 导入Less文件:@import "test.less"; //等价于@import "test"(可以不带后缀)

@import 'test1';

  • 导入css文件:@import "lib.css"; 最后引入,易导致重绘和重排,不允许使用

html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- <link rel="stylesheet" href="./01.css"> -->
    <style>
        @import "./01.css";
    </style>
</head>

<body>
    <div class="outer"></div>
</body>

</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

css

div {
  width: 200px;
  height: 200px;
  background-color: red;
}
1
2
3
4
5

# 2.10 less函数

参考文献:https://less.bootcss.com/functions/#less-%E5%87%BD%E6%95%B0

  • 逻辑函数

    • if

      @c: boo;
      div {
          margin: if((2 > 1), 1, 0);
          color:  if((iscolor(@c)), @c, black);
      }
      
      1
      2
      3
      4
      5
    • boolean

      @c: boolean(2<1);
      
      div {
          margin: if(@c, 1, 0);
      }
      
      1
      2
      3
      4
      5
  • 字符串函数

    • escape

      • 对字符串中的特殊字符做 URL-encoding 编码。
      • 这些字符不会被编码:,, /, ?, @, &, +, ', ~, ! and $
      • 被编码的字符是:**, #, ^, (, ), {, }, |, :, >, <, ;, ], [ and =
      escape('a=1') // return a%3D1
      
      1
    • e

      @mscode: "hello guigu";
      e(@mscode);
      
      1
      2
    • format

      div{
          format-a-d:%("repetitions: %a file: %d", 1 + 2, "directory/file\.less");
      }
      
      1
      2
      3
    • replace

      div{
          content:replace("One + one = 4", "one", "2", "gi");
      }
      
      1
      2
      3
  • 列表函数

    • length

      p{
      	@list: "banana", "tomato", "potato", "peach";
      	n: length(@list);
      }
      
      1
      2
      3
      4
    • extract

      div{
          @list: apple, pear, coconut, orange;
          value: extract(@list, 3);
      }
      
      1
      2
      3
      4
    • range

      div{
          value: range(4);
      }
      
      1
      2
      3
  • 数学函数

    • ceil

      ceil(2.4)
      
      1
    • floor

      floor(2.6)
      
      1
    • percentage

      percentage(0.5)
      
      
      1
      2
    • round

      round(1.67, 1)
      
      1
    • sqrt

      sqrt(324cm)
      
      1
    • abs

      abs(-18)
      
      
      1
      2
    • pow

      pow(5, 2);
      
      1
    • mod

      mod(10,6)
      
      1
    • min

      min(1,2,3,4,5)
      
      1
    • max

      max(1,2,3,4,5)
      
      1
  • 类型函数

    • isnumber

      isnumber(1);
      
      1
    • isstring

      isstring('1')
      1
    • iscolor

      iscolor(#fff);
      
      1
  • 混调函数/杂项函数

    • color

      color(red)
      
      1
    • image-size

      image-size("file.png")
      
      1
    • image-width

      image-width("file.png");
      
      1
    • image-height

      image-height("file.png");
      
      1
  • 颜色调试

    div{
        v:hsl(90, 80%, 50%);
        value: desaturate(hsl(90, 80%, 50%), 20%);
    }
    
    1
    2
    3
    4

Last Updated: 12/25/2022, 10:02:14 PM