1、什么是less
LESS是一种动态样式语言,属于CSS预处理语言的一种,它使用类似CSS的语法,为CSS的赋予了动态语言的特性,如变量、继承、运算、函数等,更方便CSS的编写和维护。我们编写的less文件最终会编译成css文件
2、如何使用less
- less官网
http://lesscss.cn/#download-options
- 使用CDN
//cdnjs.cloudflare.com/ajax/libs/less.js/2.5.3/less.min.js
- 如果使用vsCode的童靴可以使用插件
Easy LESS
3、less的语法规则
less中的注释
我们编写的less文件最终会被编译成css文件去执行,那么在less中注释分两种,一种是会被编译的注释,另一种是不会被编译的注释
左边是我们编写的less文件右边是编译后的css文件
变量的使用及语法规则
- 定义变量
@变量名 : 值; @wit : 200px;
- 使用变量
这样给我们的class设置了一个宽为200px的样式.content{ width: @wit; }
如果将属性名,或者选择器作为变量使用的话需要使用@{}
编译后的css样式//将选择器作为变量 @d : div; //将属性名作为变量 @w : width; @{d}{ @{w}: 50px; }
less中的嵌套
我们使用css写选择器的时候通常使用 .a .b{} 这样去选择具有父子关系的DOM元素,但在less中我们可以使用嵌套来表示这种父子级关系
- 基本嵌套
这样我们的层次关系非常清晰,给.content设置宽度200px,给content的子级div设置高度为200px//变量 @wit : 200px; @hei : 200px; .content{ width: @wit; div{ height: @hei; } }
编译后的css样式
但是这样使用伪类样式的时候会出问题,我们给div加一个hover伪类//变量 @wit : 200px; @hei : 200px; .content{ width: @wit; div{ height: @hei; } :hover{ background-color: black; } }
有没有发现div跟hover中间有空格,怎么去解决这个问题让中间的空格去掉 - &符号使用
在样式前面加一个&符&:hover{ background-color: black; }
如果说嵌套是交集选择器的话那我们的&就是并集选择器
less中的混合
混合就是将一系列属性从一个规则中引入到另一个规则的方式
-
普通混合
先来看一段代码.content{ width: 200px; height: 200px; background-color: red; .inner1{ width: 100px; height: 100px; border: 1px solid black; } .inner2{ width: 100px; height: 100px; border: 1px solid black; } }
这是我们的嵌套对吧,大家有没有发现一个问题,在inner1和inner2中的样式是重复的,我们写代码要避免这种重复性的工作,对于这种重复性的东西我们一般就是将它公共的东西抽取出来,在我们的Less中就是将这种事情称之为混合
.innerT{ width: 100px; height: 100px; border: 1px solid black; } .inner1{ .innerT } .inner2{ .innerT }
但是这样做有个问题,我们来看一下编译后的css文件
.a { width: 100px; height: 100px; border: 1px solid black; } .content { width: 200px; height: 200px; background-color: red; } .content .inner1 { width: 100px; height: 100px; border: 1px solid black; } .content .inner2 { width: 100px; height: 100px; border: 1px solid black; }
它将我们混合的部分也编译出来了,这是我们不想要的,怎么解决这个问题呢,看下一个混合。
-
不带输出的混合
我们给他加一个括号.a(){ width: 100px; height: 100px; border: 1px solid black; }
来看一下编译后的css文件
.innerT{ width: 100px; height: 100px; border: 1px solid black; } .inner1{ .innerT } .inner2{ .innerT }
但是这样做有个问题,我们来看一下编译后的css文件
.content { width: 200px; height: 200px; background-color: red; } .content .inner1 { width: 100px; height: 100px; border: 1px solid black; } .content .inner2 { width: 100px; height: 100px; border: 1px solid black; }
我们公共部分的样式没有输出出来吧,但是随即而来又一个问题,inner1和inner2里面的属性值都是写死的,我想要在inner1和inner2里面的数值不一样怎么办呢,用参数解决。
-
带参数的混合
.innerT(@w, @h){ width: @w; height: @h; border: 1px solid black; } .content{ .inner1{ .innerT(100px, 200px) } .inner2{ .innerT(200px, 100px) } }
用@符声明我们的形参,使用他的时候输入实参,再来看下编译后的css文件
.content .inner1 { width: 100px; height: 200px; border: 1px solid black; } .content .inner2 { width: 200px; height: 100px; border: 1px solid black; }
完美解决是吧,但是如果我想调用他的时候不给他传入实参怎么办呢。
-
带参数且有默认值的混合
我们使用@参数名 : 默认值,这种形式给他赋默认值.innerT(@w:1px, @h:1px){ width: @w; height: @h; border: 1px solid black; } .content{ .inner1{ .innerT() } .inner2{ .innerT(200px, 100px) } }
在我们调用他的时候,可以选择传参或不传参,来看一下编译后的css文件
.content .inner1 { width: 1px; height: 1px; border: 1px solid black; } .content .inner2 { width: 200px; height: 100px; border: 1px solid black; }
但是问题又来了,当我有多个参数的时候我想给指定参数赋值怎么办。
-
命名参数
我们在调用他的时候直接写出来形参名称然后赋值就好了。.inner1{ .innerT(@h:500px) }
我们来看编译后的css文件
.content .inner1 { width: 1px; height: 500px; border: 1px solid black; }
这样我们没有给参数的值使用的是默认值,我们指定的参数值已经是我们填入的值
-
匹配模式
我们用一个小Demo来理解匹配模式,用html+css写一个三角形<div id="wrap"> <div class="sjx"> </div> </div>
.triangle(){ width: 0px; height: 0px; border-width: 40px; border-style: solid; border-color: black transparent transparent transparent; } #wrap{ .sjx{ .triangle() } }
来看一下效果
这样是不是不够理想,我所有的数值都是死的,我想改变这个三角形的大小,颜色,都不能改变对吧,我们来进行优化一下。.triangle(@w:40px, @c:block){ width: 0px; height: 0px; border-width: @w; border-style: solid; border-color: @c transparent transparent transparent; }
这样将我们控制三角形大小,颜色换成了参数,在我们调用他的时候传参就可以控制三角形的大小颜色了对吧。那么我们的需求又变了,现在不单单要求他可以控制他的颜色,大小,我还要能控制三角形的方向。
有人说了,那简单啊我写四份改改他的方向不就完了吗,但是这样真的可以吗,我们来看一下。//上 .triangle(@w:40px, @c:pink){ height: 0px; width: 0px; border-width: @w; border-style: solid; border-color: @c transparent transparent transparent; } //右 .triangle(@w:40px, @c:pink){ height: 0px; width: 0px; border-width: @w; border-style: solid; border-color: transparent @c transparent transparent; } //下 .triangle(@w:40px, @c:pink){ height: 0px; width: 0px; border-width: @w; border-style: solid; border-color: transparent transparent @c transparent; } //左 .triangle(@w:40px, @c:pink){ height: 0px; width: 0px; border-width: @w; border-style: solid; border-color: transparent transparent transparent @c; } #wrap{ .sjx{ .triangle() } }
我们来看一下编译后的css文件
#wrap .sjx { height: 0px; width: 0px; border-color: pink transparent transparent transparent; border-color: transparent pink transparent transparent; border-color: transparent transparent pink transparent; border-width: 40px; border-style: solid; border-color: transparent transparent transparent pink; }
瓦特,是什么鬼这是,他将我们所有控制方向的代码都编译到了一起,这样写肯定是有问题的,我们写了四个同名方法他不知道该调用哪个了。这时候我们的匹配模式该出来了,我们需要一个匹配符,来匹配我们要调用的到底是哪个方法。
我们通过在参数列表前面加一个自定义匹配符来区分这四个方法//上 .triangle(T, @w:40px, @c:pink){ height: 0px; width: 0px; border-width: @w; border-style: solid; border-color: @c transparent transparent transparent; } //右 .triangle(R, @w:40px, @c:pink){ height: 0px; width: 0px; border-width: @w; border-style: solid; border-color: transparent @c transparent transparent; } //下 .triangle(B, @w:40px, @c:pink){ height: 0px; width: 0px; border-width: @w; border-style: solid; border-color: transparent transparent @c transparent; } //左 .triangle(L, @w:40px, @c:pink){ height: 0px; width: 0px; border-width: @w; border-style: solid; border-color: transparent transparent transparent @c; } #wrap{ .sjx{ .triangle(B) } }
我们在调用方法的时候就用自定义的匹配符当参数传递进去,它就知道我们要调用的是哪个方法了,我们来看一下编译后的css
#wrap .sjx { height: 0px; width: 0px; border-width: 40px; border-style: solid; border-color: transparent transparent pink transparent; }
已经成功解决掉了对不对,但是我们的代码是不是显得太冗余了,我们可以将混合抽取出来成模块,单独写一个less文件放进去,然后在通过@impor引进来
@import "triangle.less"; #wrap{ .sjx{ .triangle(B) } }
我们来回头看一下我们抽取出来的模块
//上 .triangle(T, @w:40px, @c:pink){ height: 0px; width: 0px; border-width: @w; border-style: solid; border-color: @c transparent transparent transparent; } //右 .triangle(R, @w:40px, @c:pink){ height: 0px; width: 0px; border-width: @w; border-style: solid; border-color: transparent @c transparent transparent; } //下 .triangle(B, @w:40px, @c:pink){ height: 0px; width: 0px; border-width: @w; border-style: solid; border-color: transparent transparent @c transparent; } //左 .triangle(L, @w:40px, @c:pink){ height: 0px; width: 0px; border-width: @w; border-style: solid; border-color: transparent transparent transparent @c; }
看似很完美对不对,但是其中还是有一些代码冗余了比如height,width,对于我们冗余的这些代码我们在进行混合
.triangle(@_, @w, @c){ width: 0px; height: 0px; } //上 .triangle(T,@w:40px, @c:block){ border-width: @w; border-style: solid; border-color: @c transparent transparent transparent; } //右 .triangle(R, @w:40px, @c:block){ border-width: @w; border-style: solid; border-color: transparent @c transparent transparent; } //下 .triangle(B, @w:40px, @c:block){ border-width: @w; border-style: solid; border-color: transparent transparent @c transparent; } //左 .triangle(L, @w:40px, @c:block){ border-width: @w; border-style: solid; border-color: transparent transparent transparent @c; }
我们在公共部分添加的@_是一个通配符,在调用的时候先执行里面的代码
这里有一个个小点大家注意一下,我们将三角形的匹配模式抽取出去单独写一个triangle.less这个文件不会编译成单独的这个文件的css文件
arguments变量
- @argument参数列表
用arguments变量省去了挨个写参数的事情,我们来看一下编译后的css文件.variable(@w, @style, @c){ border: @arguments; } .content{ .variable(1px, solid, black); }
.content { border: 1px solid black; }