2.1变量
2.1.1 变量语法
使用@
来定义变量,变量名自定义。
@color: #00f;
此时定义了一个变量color
其值为十六进制颜色值
使用变量的时候需要加上@
,表示取出color变量的值。
使用变量:
h1 {
color: @color;
}
2.1.2 变量的作用域
可以定义多个变量,但是当多个变量同名的时候,应该使用哪个变量的值呢?less和其他语言类似,采用就近原则,也即如果当前作用域下有该变量则使用该变量的值,否则逐层作用域向上查找,直到查找失败,解析错误,如果配置了File Wather
控制台会报错,并指向出错的less文件位置:
比如:
@color:#00f;
div {
@color: #f00;
color: @color;
}
此时可以看到,color使用的是最近一级的@color
变量的值
特别的是,查看以下代码:
@color:#00f;
div {
@color: #f00;
.my {
@color: #ff0;
background-color: @color;
@color: #0f0;
}
}
如果同一作用域下,使用该变量的位置比变量定义位置靠前,那么该使用哪个变量的值呢?由于less对变量的处理是先对变量统一处理,也即按照变量顺序进行处理之后,再对使用其的地方进行赋值操作,因此会使用最后一次定义变量的地方。
也即结果为:
2.1.3 字符串插值
类似于es6的模板字符串一样,可以在字符串中使用变量。
语法:
@variable: "xxx";
将变量放入到{}中
@{variable}
使用:
@url: "/images/";
div {
width: 200px;
height: 200px;
background-image: url("@{url}1.jpg"); // 结果为/images/1.jpg
}
2.1.4 选择器插值
类似于字符串插值一样,将变量放入到{}中。不同的是,选择器插值则是作为对选择器的定义
使用:
@mydiv: div;
@{mydiv} {
width: 200px;
height: 200px;
}
编译之后:
div {
width: 200px;
height: 200px;
}
2.1.5 媒体查询定义变量的方式
由于“~”后面的值是不被编译的,所以可以用作媒体查询的参数。
使用:
@mediaQuery: ~"(max-width: 600px)";
@media screen and @mediaQuery {
div {
width: 200px;
height: 200px;
background-color: #898900;
}
}
2.1.6 变量之间相互使用
-
不加
@
如果一个变量直接引用一个变量,而不加
@
,则使用该变量的值的时候,需要加上两个@
@color: #00f; @mycolor: color; div { color: @@mycolor; }
类似于先取出color,然后再对color变量进行值得提取
-
加上
@
如果引用得变量加上了
@
,表明直接使用得是值,此时和使用普通变量得用法一致@color: #00f; @mycolor: @color; div { color: @mycolor; }
2.2 混合
2.2.1 继承属性
可以在一个选择器内部引用已经定义好的类样式和ID选择器样式(只能是这两个选择器样式),那么这个选择器就可以直接使用引用的选择器样式属性
使用:
.div {
width: 200px;
height: 200px;
}
span {
.div;
}
// 编译之后的结果:
.div {
width: 200px;
height: 200px;
}
span {
width: 200px;
height: 200px;
}
可以看到引用的样式也同样出现在编译之后的文件中
2.2.2 带参数混合
带参数混合就类似函数一样的性质。
以上继承属性的方式是直接使用继承之后的属性,除此之外,还可以传入参数给继承的类/ID样式,便于动态引用,同时便于扩展
使用:
.div(@width) {
width: @width;
height: @width;
}
span {
.div(20px);// 传参过去,类似于函数
}
// 编译之后的结果
span {
width: 20px;
height: 20px;
}
可以看到引用的样式不会出现在编译之后的文件中
注意:如果继承的样式需要参数,则必须传参过去,否则会出错。
除了传递一个参数过去以外,还可以传递多个参数,多个参数之间使用分号;
分隔。
.div(@width;@height) {
width: @width;
height: @height;
}
如果存在选择器一样,参数个数不一致的情况,会出现什么情况呢?
CSS是顺序编译,当找到第一个满足要求的选择器,则进行匹配
比如:
.div(@width) {
width: @width;
height: @width;
}
.div(@width;@height) {
width: @width;
height: @height;
}
span {
.div(200px);
}
// 编译之后的结果为:
span {
width: 200px;
height: 200px;
}
由于第一个匹配成功,则继承第一个样式。
但是如果参数个数一致,选择器名称也一致呢?
只要满足要求,就进行匹配,并继承
比如:
.div(@width) {
width: @width;
}
.div(@height) {
height: @height;
}
span {
.div(200px);
}
// 编译之后的结果为:
span {
width: 200px;
height: 200px;
}
由于以上两个都匹配,所以都会继承
2.2.3 隐藏属性继承
直接继承属性,继承的父样式同样也会出现在编译之后的结果中,而带参数混合的方式继承,继承的父样式不会出现在编译之后的结果中。
有时,只是为了使用继承的公共的样式,而在html页面中不会单独使用公共样式,所以不想让公共样式出现在编译之后的结果中。
所以结合上面两种写法,可以使用隐藏属性继承的方式,既继承了公共样式,又不让其出现在编译之后的结果中。
使用:
.div() {
width: 200px;
height: 200px;
}
span {
.div();
}
// 编译之后的结果 只包含span选择器样式
span {
width: 200px;
height: 200px;
}
注意:()
不能省略
2.2.4 默认值混合
可以给参数设置默认值,这样可以使用默认值且不用传参的情况下继承样式
使用:
.div(@width: 100px) {
width: @width;
height: @width;
}
span {
.div; // 也可以是.div();
}
2.2.5 @arguments参数
类似于js中函数中内置对象arguments
一样,可以获取传递的全部参数值,less中@arguments
也可以获取全部的参数值,但也仅限于获取参数值,不能做其他操作。但是有时不想对单个参数进行操作,只用全部的参数值的时候还是很有用的。
使用:
.transition(@property: all;@duration: 4s;@delayTime: 2s;@TimingFuction: ease) {
-moz-transition: @arguments;
-webkit-transition: @arguments;
-o-transition: @arguments;
transition: @arguments;
}
span {
.transition();
}
// 编译之后的结果
span {
-moz-transition: all 4s 2s ease;
-webkit-transition: all 4s 2s ease;
-o-transition: all 4s 2s ease;
transition: all 4s 2s ease;
}
2.2.6 !important
如果给一个一个属性添加!important会很麻烦,此时可以在引用父级样式的时候加上!important,引用的父级样式中所有属性都会加上!important属性。
使用:
.div(@width;@height) {
width: @width;
height: @height;
}
span {
.div(100px,100px)!important;
}
// 编译之后的结果
span {
width: 100px !important;
height: 100px !important;
}
2.2.7 扩展运算符...
可以使用扩展运算符...
来不指明有多少个参数,而参数的获取通过@arguments
参数来获取。
使用:
.div(...) {
width: @arguments;
}
span {
.div(100px);
}
// 编译之后的结果为
span {
width: 100px;
}
2.2.8 模式匹配
只有满足匹配要求的混合才会被使用。混合中的变量可以匹配任何值,非变量形式的值只有与传入的值完全相等时才可以匹配成功。
使用:
.border(soild,@size) {
border: @size;
}
.div(@height) {
height: @height;
}
span {
.border(soild,2px);
}
只有传入的值是solid才能与.border类匹配成功,否则匹配不成功。
所以非变量形式的值也即不加@
的值,此值只是用于进行继承限定的,不用于传参使用。
2.2.9 条件混合
-
when
只有当when中的条件满足的时候,才会应用该样式
// 当@a的值大于400px的时候,才能使用改样式,等效于when(true)的时候才可以 .minin(@a) when (@a > 400px) { width: @a; } #header { .minin(500px);// 满足要求 } // 编译之后的结果为: #header { width: 500px; // 成功引入 }
而如果不满足:
.minin(@a) when (@a > 400px) { width: @a; } #header { .minin(200px); } // 编译之后的结果: 由于不满足条件,所以没有成功引入,也即没有样式
如果变量的值为false/true,变量可以单独写在when括号中。
.minin(@b) when (@b) { width:200px; } #header { .minin(false); }
-
多个条件
多个条件使用
,
进行分隔,且每个条件单独写在一个括号内。只要有一个条件满足,则这个选择器被选中。类似于或
运算。.minin(@a,@b) when (@b),(@a<= 200px) { width: @a; } #header { .minin(200px,false); } // 编译之后的结果为: #header { width: 200px; }
-
and
多个条件都满足时才被选中
.minin(@a,@b) when (@b)and(@a<= 200px) { width: @a; } #header { .minin(200px,false);// 没有被选中,没有样式输出 }
-
not
当条件不满足的时候被选中,取反操作
.minin(@b) when not(@b) { width: 200px; } #header { .minin(false); } // 编译之后的结果为: #header { width: 200px; }
not只作用于一个条件,不能作用于多个条件
.minin(@a,@b) when not(@b)and(@a> 200px) { width: @a; } #header { .minin(200px,false); } // 由于not只作用于(@b)条件,而(@a > 200px)不满足条件,所以没有样式输出
2.3 嵌套语法
Less提供了使用嵌套代替层叠或与层叠结合使用的能力。使用Less书写可以模仿HTML的组织结构
假设有以下html结构
<main>
<section>
<div></div>
</section>
</main>
编写类似于html结构的less文件,一层一层嵌套类似于使用结构选择器对元素逐层查找一样,和后代选择器效果一致。且内层嵌套会继承外层选择器属性。
main {
width: 200px;
height: 200px;
section {
width: 100%;
height: 50%;
div {
width: 50%;
height: 50%;
background-color: #0ff;
}
}
}
编译之后的css文件为:
main {
width: 200px;
height: 200px;
}
main section {
width: 100%;
height: 50%;
}
main section div {
width: 50%;
height: 50%;
background-color: #0ff;
}
2.3.1 &的用法
&
表示对父选择器的引用,一般用在伪类选择器上。
在一个内层选择器的前面,如果没有 & 符号,则这个内层选择器会被解析为父选择器的后代。如果内层选择器前面有一个 & 符号,则内层选择器会被解析为父选择器自身或父选择器的伪类。
有以下html代码:
<main>
</main>
需要选中当鼠标悬浮时的样式,也即main:hover
,
如果是以下写法:
main {
width: 200px;
height: 200px;
main:hover {
background: #000;
}
}
因为嵌套方式是选择后代元素,所以编译之后的结果是:
main {
width: 200px;
height: 200px;
}
main main:hover {
background: #000;
}
显然不是我们想要的结果,我们并不想要作为后代选择器的方式出现,而是兄弟选择器的方式并排出现,所以此时可以使用&
main {
width: 200px;
height: 200px;
&:hover {
background: #000;
}
}
以上代码的解析过程是:当解析到&的时候,&会被选择器替换替换,且与父选择器出现在同一层,也即:
main {
width: 200px;
height: 200px;
}
main:hover {
background: #000;
}
应用:
2.3.1.1 重复引用父选择器
.my {
width: 200px;
height: 200px;
&-one {
background-color: #f00;
}
&-two {
background-color: #00f;
}
&-three {
background-color: #ff0;
}
}
编译之后的结果为:
.my {
width: 200px;
height: 200px;
}
.my-one {
background-color: #f00;
}
.my-two {
background-color: #00f;
}
.my-three {
background-color: #ff0;
}
2.3.1.2 更改选择器的顺序
有些时候可能需要将内层选择器放在父选择器之前,此时我们可以将 & 放在当前选择器后面来完成。
.my {
width: 200px;
height: 200px;
main & {
background-color: #00f;
}
}
编译之后的结果为:
.my {
width: 200px;
height: 200px;
}
main .my {
background-color: #00f;
}
2.4 命名空间
出于组织结构或仅仅是为了提供一些封装的目的,可以对混合进行分组。对一些冲突的变量规范于不同的命名空间中,同时也便于多次重复使用与扩展。
定义一个命名空间,可以使用任何的类/ID选择器,作为命名空间,此时命名空间的性质类似于函数。
.my() {
}
这里定义了一个命名空间.my,加上(),使其在编译之后的文件中不输出。
接着便可以在这个命名空间中书写混合。
.my() {
.a {
width: 20px;
height: 20px;
.b {
width: 200px;
height: 200px;
}
&:hover {
background-color: #0ff;
}
}
}
使用命名空间中的混合。类似于后代选择器一样选择指定的选择器进行使用。
这里使用>
表用来选择
.header {
.my>.a;
}
// 结果为:
.header {
width: 20px;
height: 20px;
}
.header .b {
width: 200px;
height: 200px;
}
.header:hover {
background-color: #0ff;
}
以上代码的意思表示:选择命名空间中的.a选择器作为我要引入的样式,所以.a中的样式被全部引入到.header选择器中,感觉就好像.header替代了.a一样。
如果再先下一层引入呢?
.header {
.my>.a>.b;
}
// 结果为:
.header {
width: 200px;
height: 200px;
}
以上代码就很好解释了,选择命名空间中.b选择器作为要引入的样式,所以.b中的样式被全部引入到.header选择器中,感觉就好像.header替代了.b一样。
除了可以使用>
表示逐层选择,还可以使用空格
以下代码效果一致:
.header {
.my .a .b;
}
// 结果为:
.header {
width: 200px;
height: 200px;
}