前端构建:Less入了个门

Posted X-JoNNeY

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端构建:Less入了个门相关的知识,希望对你有一定的参考价值。

一、前言                             

  说到前端构建怎能缺少CSS预处理器呢!其实CSS的预处理器有很多啦,比较出名的有Scss、Sass、Stylus和Less。(最近还听说出现了Autoprefixer等CSS后处理器,可参考@一丝的PPT)

  众多CSS预处理器中Less的语法最接近原生CSS,因此相对来说更容易上手,假如有JS、C#等编程经验的话,其实上述的几种预处理器的学习成本也不会特别高。下面是我们这阵子的学习笔记,以便日后查阅。

  最好的入门教程——官网地址:http://lesscss.org/

  最佳实践之一——Bootstrap

  由于内容较多,特设目录一坨:

  二、搭建学习环境

  三、内联样式和外联样式

  四、语法

    1. 注释

    2. 变量(Variable)

        列表类型

    3. 嵌套(Nested)

    4. 父选择器引用(ParentSelector)

  5. 导入指令(Import)

    6. 继承(Extend)

   6.1. 父选择器必须严格匹配,除了属性选择器中属性值引号不必匹配外,或添加all关键字外。

   6.2. 父选择器不支持变量形式

   6.3. media query影响继承的作用域

    6.3.1. media query内的extend操作,仅能继承当前块的其他选择器样式。

    6.3.2. 非media query内的extend操作,将会继承所有media query中匹配的选择器样式。

   6.4. 增强的mixin定义mixin时仅能使用类选择器和ID选择器,而extend操作可对应所有的选择器,因此当没有动态入参而又需要类选择器和ID选择器以外的选择器时,可使用extend来实现mixin的功能。

    7. 混合(Mixin)

  7.1. 类选择器、ID选择器自动被定义为mixin,而且具有命名空间;

  7.2. 显示定义不带参数和带参数的样式库(mixin库),不会输出到最终输出中,仅供调用;

  7.3. mixin的中内置两个特殊的对象@arguments和@reset。@argumentsk代表mixin的所有入参,而@reset代表mixin的...入参数组。

  7.4. mixin的重载可定义多个同名mixin,调用时只要参数数量匹配则会执行相应的mixin。

    8. 选择、循环作业控制

  五、运算符

  六、函数

   1. default函数

     2. escape函数

     3. 颜色处理函数

  七、通过Lessc将Less引入开发环境

  八、实战一下

  九、与Grunt结合  

  十、总结

二、搭建学习环境                          

  搭建Less的学习环境非常简单,只需在</body>标签前通过<script type="text/javascript" src="less.js"></script>引入处理器即可实现浏览器端中将less预编译为css样式。更有效的方式是通过如下 代码监测less样式,自动编译为css样式,从而减少我们修改less代码后需按F5后才看到实际效果的繁琐步骤。

<script>less = { env: \'development\'};</script>
<script src="less.js"></script>
<script>less.watch();</script>

 

三、内联样式和外联样式                      

  基于我们现在使用的是浏览器端进行预编译,因此Less可用于内联样式和外联样式当中。

内联样式如下:

<style type="text/less">
  // less 代码
</style>

外联样式引入如下:

<link rel="stylesheet/less" type="text/css" href="文件.less"/>

 

四、语法                              

  1. 注释

// 单行注释,不会作为最终输出
/* 
    多行注释,以原生CSS的/*注释....*/形式作为最终输出
 */

  2. 变量(Variable)

     Less中的变量有以下规则:

  1. 以@作为变量的起始标识,变量名由字母、数字、_和-组成
  2. 没有先定义后使用的规定;
  3. 以最后定义的值为最终值
  4. 可用于rule值rule属性rule属性部件选择器选择器部件字符串拼接
  5. 定义时 "@变量名: 变量值;" 的形式;引用时采用 "@变量名" 或 "@{变量名}" 的形式;
  6. 存在作用域,局部作用域优先级高于全局作用域

   Less源码:

复制代码
  @color: color;
  @dialog: .dialog;
  @suffix: fix;
  // 空格将被忽略,若要保留空格则需要使用单引号或双引号
  @hi: \'hello \';
  @dear: there  ;
      
  .dialog{
    // 用于 rule属性部件,必须使用"@{变量名}" 的形式
     background-@{color}: #888;
     // 用于 rule属性,必须使用"@{变量名}" 的形式
     @{color}: blue;
  }
  // 用于 选择器,必须使用"@{变量名}" 的形式
  @{dialog}{
     width: 200px;
  }
  @{dialog}::after{
     content: \': @{hi}@{dear}!\';    // 用于 字符串拼接,必须使用"@{变量名}" 的形式
  }
  @h: 1000px;
  // 用于 选择器部件,必须使用"@{变量名}" 的形式
  .ie-@{suffix}{
    @h: 30px; // 存在作用域,局部作用域优先级高于全局作用域。
     height: @h; // 用于 属性值,两种形式均可使用
     line-height: 30px;
  }
      
  // 1. 以@作为变量的起始标识,变量名由字母、数字、_和-组成
  // 2. 没有先定义后使用的规定;
  @dialog-border-color: #666;
  @dialog-border-width: 10px;
  @dialog-border-width: 1px; // 3. 以最后定义的值为最终值;
复制代码

    最终输出:

复制代码
.dialog {
  background-color: #888;
  color: blue;
}
.dialog {
  width: 200px;
}
.dialog::after {
  content: \': hello there!\';
}
.ie-fix {
  height: 30px;
  line-height: 30px;
}
复制代码

    列表类型

    less变量除了支持#FFF,12px,12,test等单值类型外,还支持列表类型,通过内置函数extract通过索引获取列表元素,通过内置函数length获取列表的元素个数

@colors: #FFF, #0F0, #F0F;
.skin{
  color: extract(@colors, 0);
  height: 12px * length(@colors);
}

   最终输出:

.skin{
  color: #FFF;
  height: 36px;
}

  3. 嵌套(Nested)

  Less源码:

复制代码
.main{
  padding: 10px;
   > div {
     width: 100px;
   }
   .aside {
     width: 200px;
   }
  }
    
复制代码

  最终输出:

复制代码
.main {
  padding: 10px;
}
.main > div {
  width: 100px;
}
.main .aside {
  width: 200px;
}
复制代码

  4. 父选择器引用(ParentSelector)

  1. 采用&引用完整的父选择器
  2. 可通过追加和预追加的方式加工&,从而生成新的选择器
  3. 通过&::after等方式添加伪元素、伪类样式规则集合
  4. 同一个选择器可使用多个&
  5. 通过在选择器后添加 "空格&"的方式,可将当前选择器排列到最前面
  6. &指向组选择器时,会生成新的组选择器

  Less源码:

复制代码
 /* 
  * 采用&引用完整的父选择器
  * 可通过追加和预追加的方式加工&,从而生成新的选择器
  * 通过&::after等方式添加伪元素样式规则集合
  * 同一个选择器可使用多个&
  * 通过在选择器后添加 "空格&"的方式,可将当前选择器排列到最前面
  */
@bg: #aaa;
#ps1 .btn{
  background-color: @bg;
   border-radius: 5px;
   &:hover{
     background-color: lighten(@bg, 30%);
      cursor: pointer;
   }
   &-msg, &-eof{
     color: blue;
   }
   .no-borderradius &{
     background-image: url(\'img/btn-bg.png\');
   }
}
/*
 * &指向组选择器时,会生成新的组选择器
 */
#dummy1, .dummy1{
  &:hover{
     color: red;
    }
   & + &{
     font-size: 12px;
   }
}
复制代码

      最终输出:

复制代码
/* 
 * 采用&引用完整的父选择器
 * 可通过追加和预追加的方式加工&,从而生成新的选择器
 * 通过&::after等方式添加伪元素样式规则集合
 * 同一个选择器可使用多个&
 * 通过在选择器后添加 "空格&"的方式,可将当前选择器排列到最前面
 */
#ps1 .btn {
  background-color: #aaaaaa;
  border-radius: 5px;
}
#ps1 .btn:hover {
  background-color: #f6f6f6;
  cursor: pointer;
}
#ps1 .btn-msg,
#ps1 .btn-eof {
  color: blue;
}
.no-borderradius #ps1 .btn {
  background-image: url(\'img/btn-bg.png\');
}
/*
 * &指向组选择器时,会生成新的组选择器
 */
#dummy1:hover,
.dummy1:hover {
  color: red;
}
#dummy1 + #dummy1,
#dummy1 + .dummy1,
.dummy1 + #dummy1,
.dummy1 + .dummy1 {
  font-size: 12px;
}
复制代码

5. 导入指令(Import)

  less样式文件可通过 @import \'文件路径\'; 引入外部的less文件。

  注意:

  1. 不带扩展名或带非.less的扩展名均被视为less文件;
  2. @import可出现在任何位置,而不像css的@import那样只能放在文件第一行。

  另外@import还提供了6个可选配置项(分别为reference,inline,less,css,once,multiple),用来改变引入文件的特性。语法为:  @import (reference) \'文件路径\'; 。下面为各配置项的具体说明:

1. @import (reference) "文件路径"; 
  将引入的文件作为样式库使用,因此文件中样式不会被直接编译为css样式规则。当前样式文件通过extendmixins的方式引用样式库的内容。
2. @import (inline) "文件路径"; 
  用于引入与less不兼容的css文件,通过inline配置告知编译器不对引入的文件进行编译处理,直接输出到最终输出。注意:引入的文件和当前文件会被编译为一个样式样式
3. @import (less) "文件路径"; 
  默认使用该配置项,表示引入的文件为less文件。
4. @import (css) "文件路径"; 
  表示当前操作为CSS中的@import操作。当前文件会输出一个样式文件,而被引入的文件自身为一个独立的样式文件
5. @import (once) "文件路径"; 
  默认使用该配置项,表示对同一个资源仅引入一次。
6. @import (multiple) "文件路径"; 
  表示对同一资源可引入多次。

  6. 继承(Extend)

  有两种语法形式, <selector>:extend(<parentSelector>){} 和 <selector>{ &:extend(<parentSelector>); } 

   Less源码:

复制代码
.animal{
  color: #fff;
}
/* 语法1:<selector>:extend(<parentSelector>){} */
.bear:extend(.animal){
  width: 100px;
  height: 100px;
}
/* 语法2:<selector>{ &:extend(<parentSelector>); } */
.deer{
  &:extend(.animal);
  width: 50px;
  height: 50px;
}
复制代码

   最终输出:

复制代码
.animal,
.bear,
.deer {
  color: #fff;
}
/* 语法1:<selector>:extend(<parentSelector>){} */
.bear {
  width: 100px;
  height: 100px;
}
/* 语法2:<selector>{ &:extend(<parentSelector>); } */
.deer {
  width: 50px;
  height: 50px;
}
复制代码

注意事项:

  6.1. 父选择器必须严格匹配,除了属性选择器中属性值引号不必匹配外,或添加all关键字外。
  Less源码:
复制代码
*.parent{
  height: 100px;
   .hair{
     color: #f27;
   }
   [name=eyes]{
     color: #768;
   }
}
// 匹配失败
.son:extend(.parent){}
.son:extend(.hair){}
          
// 匹配成功
.son:extend(*.parent [name=\'eyes\']){}
.son:extend(*.parent [name="eyes"]){}
// all关键字会匹配所有包含parentSelector内容的选择器,并以selector替换parentSelector来生成新的选择器
// 下面的内容会生成 *.son,*.son .hair,*.son [name=eyes]三个新的选择器
.son:extend(.parent all){}
复制代码

  最终输出:

复制代码
*.parent,
*.son {
  height: 100px;
}
*.parent .hair,
*.son .hair {
  color: #f27;
}
*.parent [name=eyes],
.son,
.son,
*.son [name=eyes] {
  color: #768;
}
复制代码

 6.2. 父选择器不支持变量形式

 Less源码:

复制代码
@p1: .parent1;
@p2: .parent2;
.parent1{
  height: 100px;
}
@{p2}{
  height: 200px;
}
// 匹配失败
// 形式1,不支持以变量作入参
.son1:extend(@{p1}){}
// 形式2,不支持以变量作为选择器的规则集合
.son1:extend(.parent2){}
          
// 匹配成功
.son2:extend(.parent1){}
@s3: son3;
.@{s3}:extend(.parent1){}     
复制代码

  最终输出:

复制代码
.parent1,
.son2,
.son3 {
  height: 100px;
}
.parent2 {
  height: 200px;
}
复制代码

6.3. media query影响继承的作用域

  6.3.1. media query内的extend操作,仅能继承当前块的其他选择器样式。

      注意:不能extend当前media query块内部的子media query块中的选择器样式;但可以extend父media query块的选择器样式。

    Less源码:

复制代码
.parent1{
  height: 200px;
}
@media screen{
  .parent1{
    height: 100px;
  }    
   // 无法继承子media query块的选择器样式
   .son1:extend(.parent2){}
   @media (min-width: 1023px){
     // 继承父media query块的选择器样式
      .son2:extend(.parent1){}
      .parent2{
        width: 200px;
      }
   }
}   
复制代码

    最终输出:

复制代码
.parent1 {
  height: 200px;
}
@media screen {
  .parent1 {
    height: 100px;
  }
}
@media screen and (min-width: 1023px) {
  .parent2 {
    width: 200px;
  }
}
复制代码

  6.3.2. 非media query内的extend操作,将会继承所有media query中匹配的选择器样式。

   Less源码:

复制代码
@media screen{
  .parent{
     height: 100px;
   }
   @media (min-width: 1023px){
     .parent{
         width: 200px;
       }
   }
}
.son:extend(.parent){}
复制代码

  最终输出:

复制代码
@media screen {
  .parent,
  .son {
    height: 100px;
  }
}
@media screen and (min-width: 1023px) {
  .parent,
  .son {
    width: 200px;
  }
}
复制代码

 6.4. 增强的mixin定义mixin时仅能使用类选择器和ID选择器,而extend操作可对应所有的选择器,因此当没有动态入参而又需要类选择器和ID选择器以外的选择器时,可使用extend来实现mixin的功能。

7. 混合(Mixin)

  Mixin相当于macro,会将样式规则内联到调用的位置中。而Less中的mixin有以下的注意点:

  7.1. 类选择器、ID选择器自动被定义为mixin,而且具有命名空间;
  Less源码:
复制代码
.animal{
  .human{
     #fsjohnhuang{
        .hair{
            color: #000;
          }
       }    
    }    
}    
.front-end-monkey{
  // 或者.animal.human#fsjohnhuang.hair();
  // 或者.animal>.human>#fsjohnhuang>.hair;
   // 或者.animal>.human>#fsjohnhuang>.hair();
   // 即可调用mixin
   .animal.human#fsjohnhuang.hair;
}
复制代码

  最终输出:

.animal .human #fsjohnhuang .hair {
  color: #000;
}
.front-end-monkey {
  color: #000;
}

  7.2. 显示定义不带参数和带参数的样式库(mixin库),不会输出到最终输出中,仅供调用;

  Less源码:

复制代码
// 定义不带参数的mixin
.animal(){
  color: #000;
}
// 定义带参数的mixin
// 注意:由于,和;均可用于作为参数分隔符,但由于如background、border等样式属性支持属性值组,而,则作为属性值组元素分隔符,因此推荐使用;作为参数分隔符
.dog(@type; @age){
  height: @type * @age * 12px;
}
// 定义带参数默认值的mixin
.cat(@type; @age:1){
  height: @type * @age * 5px;
}
          
// 调用才会出现在最终输出
.chihuahua{
  .dog(1;2);
} 
复制代码

  最终输出:

.chihuahua {
  height: 24px;
}

  7.3. mixin内置两个特殊的对象 @arguments 和 @reset 。@arguments代表mixin的所有入参,而@reset代表mixin的...入参数组。

  Less源码:

复制代码
.dog(@type;@age;@rest...){
  height: @type * @age * 12px;
  border: @rest;
}
.cat(@solid;@w;@color){
  border: @arguments;
}
          
.chihuahua{
  .dog(1;2;solid;1px;red);    
}
.mimi{
  .cat(solid;2px;blue);    
}
复制代码

  最终输出:

复制代码
.chihuahua {
  height: 24px;
  border: solid 1px red;
}
.mimi {
  border: solid 2px blue;
}
复制代码

  7.4. mixin的重载可定义多个同名mixin,调用时只要参数数量匹配则会执行相应的mixin。

  Less源码:

复制代码
.dog(@name){
  &::after{
    content: @name;
   }
}
.dog(@name;@age){
  height: @age * 4px;
}
.dog(@name;@age;@width:20px){
  height: @age * 12px;
  width: @width;
}
// 仅匹配到 .dog(@name){
.one-dog{
  .dog(\'chihuahua\');
}    
// 匹配到.dog(@name;@age) 和 .dog(@name;@age;@width:20px)
 .two-three-dog{
   .dog(\'two-three-dog\', 2);
}
          
// 参数的模式匹配
// 当第一参数值为mimi时调用该mixin
.cat(mimi, @age){
  height: @age * 22px;    
}
// 当第一参数值为mini时调用该mixin
.cat(mini, @age){
  height: @age * 12px;    
}
// 不管第一参数值为啥均调用该mixin
.cat(@any, @age){
  color: #f3c;
}
.mycat{
  .cat(mini, 1);
}
复制代码

  最终输出:

复制代码
.one-dog::after {
  content: \'chihuahua\';
}
.two-three-dog {
  height: 8px;
  height: 24px;
  width: 20px;
}
.mycat {
  height: 12px;
  color: #f3c;
}
复制代码

 8. 选择、循环作业控制

     Less中通过混合(Mixin)后的when关键字来提供选择的作业控制,通过递归来实现循环的作业控制。

  Less源码:

复制代码
// 条件匹配
// true值匹配,仅实参为true时才匹配成功
.truth(@a) when (@a){
  &::after{
  content: @a;
  }
}
// 匹配成功
.truth1{
  .truth(true);
}
// 匹配失败
.truth2{
  .truth(#fff);
}
          
/* 类型判断函数
 * iscolor
 * isnumber
 * isstring
 * iskeyword
 * isurl
 */
.bear(@color) when (iscolor(@color)){
  color: @color;
}
/* 单位判断函数
 * ispixel
 * ispercentage
 * isem
 * isunit
 */
.bear(@height) when (ispixel(@height)){
  height: @height;
}
// =,>,>=,<=,< 关系运算符
.rich(@h) when (@h > 1000){
  height: @h;    
}
// and、not、or(使用,号表示) 逻辑运算符
.huge(@h, @w) when (@h > 180) and (@w > 180){
  height: @h;
  width: @w;
}
// 使用& when()实现if语句
@debug: true;
& when (@debug){
  div{
    border: solid 1px red;
    }
}
          
// 通过递归实现循环
.generate-columns(4);
.generate-columns(@n, @i: 1) when (@i =< @n) {
  .column-@{i} {
    width: (@i * 100% / @n);
  }
   .generate-columns(@n, (@i + 1));
}
复制代码

  最终输出:

复制代码
.truth1::after {
  content: true;
}
/* 类型判断函数
 * iscolor
 * isnumber
 * isstring
 * iskeyword
 * isurl
 */
/* 单位判断函数
 * ispixel
 * ispercentage
 * isem
 * isunit
 */
div {
  border: solid 1px red;
}
.column-1 {
  width: 25%;
}
.column-2 {
  width: 50%;
}
.column-3 {
  width: 75%;
}
.column-4 {
  width: 100%;
}
复制代码

 

五、运算符                            

  Less还支持+、-、*、/运算符。但对单位不一致的运算数进行运算要注意以下两点:

  1. 运算数与运算符间必须用空格分隔;

  2. 以第一个运算数的单位作为运算结果的单位;

    Less源码:

复制代码
// 运算数与运算符间没有空格
@fail: 1px +2em;
.fail{
  height: @fail;
}

@success1: 1px + 2em;
.success1{
  height: @success1;
}

@success2: 2px + 1em;
.success2{
  height: @success2;
}
复制代码

    最终输出:

复制代码
.fail{
  height: 1px 2em;
}

.success1{
  height: 3px;
}

.success2{
  height: 3em;
}
复制代码

 

六、函数                              

  Less为我们提供了一个功能强大的内置函数库,其中绝大部分为颜色处理函数。下面着重介绍Misc Function中的default函数、String Function中的escape函数和颜色处理函数。

  1. default函数

     示例:

复制代码
// for teenager
.person(@age) when (@age <= 19) and (@age >=13){
  height: @age * 10px;
}
// for child
.person(@age) when (@age <13){
  height: @age * 6px;
}
// for adult
.person(@age) when (default()){
  height: 180px;
}

.son{
  .person(10);
}
.daughter{
  person(17);
}
.father{
 .person(27);
}
复制代码

    最终输出:

复制代码
.son{
  height: 60px;
}
.daughter{
  height: 170px;
}
.father{
  height: 180px;
}
复制代码

    虽然上述示例逻辑上不合理。但可以看出default函数用于条件控制当中,充当else或switch语句中default的角色。

    通过官网提供的综合示例我们可以更好理解它的用法:

复制代码
// Less源码
.x {
  .m(red)                                    {case-1: darkred}
  .m(blue)                                   {case-2: darkblue}
  .m(@x) when (iscolor(@x)) and (default())  {default-color: @x}
  .m(\'foo\')                                  {case-1: I am \'foo\'}
  .m(\'bar\')                                  {case-2: I am \'bar\'}
  .m(@x) when (isstring(@x)) and (default()) {default-string: and I am the default}

  &-blue  {.m(blue)}
  &-green {.m(green)}
  &-foo   {.m(\'foo\')}
  &-baz   {.m(\'baz\')}
}

// 最终输出
.x-blue {
  case-2: #00008b;
}
.x-green {
  default-color: #008000;
}
.x-foo {
  case-1: I am \'foo\';
}
.x-baz {
  default-string: and I am the default;
}
复制代码

   注意:

     1. default函数必须在条件控制语句当中使用;

     2. default函数可实现比else更复杂的功能,如下:

复制代码
// Less源码
.mixin(@value) when (ispixel(@value)) {width: @value}
.mixin(@value) when not(default())    {padding: (@value / 5)}

div-1 {
  .mixin(100px);
}

div-2 {
  /* ... */
  .mixin(100%);
}

// 最终输出:
div-1 {
  width: 100px;
  padding: 20px;
}
div-2 {
  以上是关于前端构建:Less入了个门的主要内容,如果未能解决你的问题,请参考以下文章

学习日志

leetcodeSQL相关的题目

Arch Linux怎样构建一个简单的软件包

因果推断中期学习小结

因果推断中期学习小结

SpringBoot整合RabbitMQ之整合配置篇