CSS预处理器 Less

967 阅读5分钟

引言

  • CSS困境:经常看到一个标签上存在很多样式类名,在这种模式中我们要时常关注CSS的优先级,避免样式的重叠覆盖。
  • 预编译器让 CSS 变成一门 可以使用 变量 、循环 、继承 、自定义方法等多种特性的标记语言,逻辑性得以大大增强

具有代表性的:Sass、Less 、Stylus

Sass 诞生于 2007 年,Ruby 编写,其语法功能都十分全面,可以说 它完全把 CSS 变成了一门编程语言。另外 在国内外都很受欢迎,并且它的项目团队很是强大 ,是一款十分优秀的预处理语言。

Stylus 诞生于 2010 年,来自 Node.js 社区,语法功能也和 Sass 不相伯仲,是一门十分独特的创新型语言。

Less 诞生于 2009 年,受Sass的影响创建的一个开源项目。 它扩充了 CSS 语言,增加了诸如变量、混合(mixin)、函数等功能,让 CSS 更易维护、方便制作主题、扩充(引用于官网)。

  • Sass 与 Stylus 相比于 Less 功能更为丰富,但对于学习成本以及适应时间 ,Less 稍胜一筹。

  • Less 没有去掉任何 CSS 的功能,而是在现有的语法上,增添了许多额外的功能特性,所以学习 Less 是一件非常舒服的事情。

Less中文官网

开始使用

使用Less有两种方式

  • 页面中引入 Less.js
    • 可在官网下载
    • 或使用CDN
    <script src="//cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js"></script>
    
    注意:link 标签一定要在 Less.js 之前引入,并且 link 标签的rel 属性要设置为stylesheet/less
    <link rel="stylesheet/less" href="style.less">
    <script src="less.min.js"></script>
    
  • 命令行使用npm安装
    npm install -g less
    
    具体使用命令
    $ lessc styles.less > styles.css
    

less语法

注释

  • //开头的注释,不会被编译到css文件中
  • /**/包裹的注释会被编译到css文件中

变量

同一个值重复多次时

  • 属性值变量:以@开头定义变量,使用时直接键入@名称
/* Less */
@color: #999;
@bgColor: skyblue;//不要添加引号
@width: 50%;
#wrap {
  color: @color;
  background: @bgColor;
  width: @width;
}

/* 生成后的 CSS */
#wrap {
  color: #999;
  background: skyblue;
  width: 50%;
}
  • 选择器/属性名/URL变量:以@开头定义变量,使用时@{名称}
/* Less */
//->LESS代码
    .@{selector} {
        width: 100px;
        height: 100px;
        @{property}: #000;  //大括号包裹
        background: url("@{bgImg}/test.png");
    }
    @selector: box;
    @bgImg: "../img";
    @property: color;
  • 变量的延迟加载块作用域就近原则

嵌套

  • 基本嵌套规则
  • &的使用:&代表的上一层选择器的名字
/* Less */
#header{
  &:after{
    content:"Less is more!";
  }
  .title{
    font-weight:bold;
  }
  &_content{//理解方式:直接把 & 替换成 #header
    margin:20px;
  }
}
/* 生成的 CSS */
#header::after{  //&嵌套
  content:"Less is more!";
}
#header .title{ // 基本嵌套
  font-weight:bold;
}
#header_content{//没有嵌套!
    margin:20px;
}

混合(Mixins)

Less 允许我们将已有的 classid 的样式应用到另一个不同的选择器上

  • 普通混合
    //LESS代码
    .public {
        width: 100px;
        height: 100px;
    }
    nav ul {
        .public;
        list-style: none;
    }
    //编译为CSS的结果
    .public {
        width: 100px;
        height: 100px;
    }
    nav ul {
        width: 100px;
        height: 100px;
        list-style: none;
    }
    
  • 不带输出的混合
    //LESS代码
    //在选择器后面加上()就可以不编译这个样式了
    .public() {
        width: 100px;
        height: 100px;
    }
    nav ul {
        .public;//如果public有子孙元素的样式,同样也会被复制过来
        list-style: none;
    }
    //编译为CSS的结果
    //此处没有.public啦
    nav ul {
        width: 100px;
        height: 100px;
        list-style: none;
    }
    
  • 带默认参数的混合
    /*Less*/
    #circle(@size: 25px){
         background-color: #4CAF50;
         border-radius: 100%;
    
         width: @size;
         height: @size;
    }
    
    #small-circle{
         #circle
    }
    
    #big-circle{
         #circle(100px)
    }
    /* 生成的 CSS */
    #small-circle {
        background-color: #4CAF50;
         border-radius: 100%;
          width: 25px;
          height: 25px;
    }
    #big-circle {
        background-color: #4CAF50;
         border-radius: 100%;
         width: 100px;
         height: 100px;
    }
    
  • 匹配模式
    • 按照模式进行匹配,要会找到方法中匹配程度最高的,进行样式覆盖替换。
    • 所有模式共用的样式,用@_
    /* Less */
    .triangle(top,@width:20px,@color:#000){
        border-color:transparent  transparent @color transparent ;
    }
    .triangle(right,@width:20px,@color:#000){
        border-color:transparent @color transparent  transparent ;
    }
    
    .triangle(bottom,@width:20px,@color:#000){
        border-color:@color transparent  transparent  transparent ;
    }
    .triangle(left,@width:20px,@color:#000){
        border-color:transparent  transparent  transparent @color;
    }
    .triangle(@_,@width:20px,@color:#000){
        border-style: solid;
        border-width: @width;
    }
    #main{
        .triangle(left, 50px, #999)
    }
    /* 生成的 CSS */
    #main{
     border-color:transparent  transparent  transparent #999;
     border-style: solid;
     border-width: 50px;
    }
    
  • arguments变量
    /* Less */
    .border(@a:10px,@b:50px,@c:30px,@color:#000){
         border:solid 1px @color;
         box-shadow: @arguments;//指代的是 全部参数
    }
    #main{
         .border(0px,5px,30px,red);//必须带着单位
    }
    /* 生成的 CSS */
    #main{
         border:solid 1px red;
         box-shadow:0px,5px,30px,red;
    }
    

运算

在Less中可以进行加减乘除的运算,我们可以做属性值颜色的运算,这样就可以实现属性值之间的复杂关系。

  • 加减法时 以第一个数据的单位为基准
  • 乘除法时 注意单位一定要统一
/* Less */
@width:300px;
@color:#222;
#wrap{
  width:@width-20;
  height:@width-20*5;
  margin:(@width-20)*5;
  color:@color*2;
  background-color:@color + #111;
}

/* 生成的 CSS */
#wrap{
  width:280px;
  height:200px;
  margin:1400px;
  color:#444;
  background-color:#333;
}

LESS 提供了一系列的颜色运算函数:颜色会先被转化成 HSL 色彩空间, 然后在通道级别操作

lighten(@color, 10%);     // return a color which is 10% *lighter* than @color
darken(@color, 10%);      // return a color which is 10% *darker* than @color

LESS提供了一组方便的数学函数

round(1.67); // returns `2`
ceil(2.4);   // returns `3`
floor(2.6);  // returns `2`

继承

  • extend 关键字的使用
/* Less */
.animation{
    transition: all .3s ease-out;
    .hide{
      transform:scale(0);
    }
}
#main{
    &:extend(.animation);
}
#con{
    &:extend(.animation .hide);
}

/* 生成后的 CSS */
.animation,#main{
  transition: all .3s ease-out;
}
.animation .hide , #con{
    transform:scale(0);
}
  • all全局搜索替换
//使用选择器匹配到的 全部声明。
/* Less */
#main{
  width: 200px;
}
#main {
  &:after {
    content:"Less is good!";
  }
}
#wrap:extend(#main all) {}

/* 生成的 CSS */
#main,#wrap{
  width: 200px;
}
#main:after, #wrap:after {
    content: "Less is good!";
}

extend 与 方法的差别

  • extend 是同个选择器共用同一个声明
  • 方法是使用自己的声明,增加了代码的重复性