# Less 笔记
Less 是一种动态样式语言,属于 css 预处理器的范畴,他扩展了 CSS 语言,增加了变量、mixin、函数的等特性,使 css 更易于维护和扩展 Less 既可以在客户端运行,也可以借助 Node.js 在服务端运行
# Less 的引入
Less 官网提供了服务器端的部署方法,我们不需要,因为 1. 这相当于是再服务器端编译,影响运行 2. 我们用本地环境所以只需要一个编译工具把 less 编译成 css
可以去 less 官网下载 less.js,这相当于是用 js 文件对代码进行编译,所以,js 的 link 要写在 less 代码后面,但是很明显这样的编译是再运行时编译,影响时间。实际上可以使用 IDE 插件实时编译,这相当于是开发的时候编译,不影响时间
# Less 基础
# Less 中的注释
以 //
开头的是单行注释,这种注释在 css 中没有,所以不会被编译到 CSS 中
以 /**/
包围的是多行注释,和 CSS 语法一样,会被编译到 CSS 中
# Less 中的变量
定义变量用 @
开头,例如
@Col:pink; | |
div{ | |
background-color:@color; | |
} |
以上是将属性值作为变量,还可以将选择器,属性、字符串的一部分作为变量 但是使用的时候要这么写 @{XXX}
@Col:pink; | |
@bgc:background-color; | |
@sel:div; | |
@{sel}{ | |
@{bgc}:@color; | |
} |
修改属性值和声明一样
Less 中的变量都是延迟加载的,Less 中的变量都是块级作用域
例如
@var:0; | |
div{ | |
@var:1; | |
table{ | |
@var:2; | |
left:@var; | |
@var:3; | |
} | |
right:@var; | |
} |
首先变量是块级作用域,所以 right
的值是不受 table
内部的修改而影响,为 1
然后变量是延迟加载的,所以编译器在看到 left:@var;
直接计算替换,而是把一个块跑完得到 @var:3
然后载进行替换的,所以 left 为 3
# Less 中的嵌套规则
我们有时需要对变量的某些状态进行设置例如 div:hover
这个时候根据嵌套的思想,应该写成
div{ | |
... | |
:hover{ | |
... | |
} | |
} |
但是编译不出来,编译器会认为这里的 :hover
是一个选择器,所以 css 会显示为
div{ | |
... | |
} | |
div :hover{ | |
... | |
} |
多了一个空格导致了编译失败,我们不希望有这个空格,我们不希望他是层级关系,要加上一个 &
div{ | |
... | |
&:hover{ | |
... | |
} | |
} |
这样空格就会消失,这里的 &
代表平级
# Less 中的混合
当我想为同级元素设置相同的样式的时候我们可以用 ,
并集选择器直接选择,但是对于不同级的,我们希望可以像引入代码块一样直接插入相关代码从而减少冗余代码,这时就用到了混合。
# 普通混合
Less 中定义混合以点开头,和 CSS 写类一样,调用直接写上去
.cent{ | |
left:0; | |
right:0; | |
} | |
div{ | |
.inner1{ | |
.cent; | |
... | |
} | |
.inner2{ | |
.cent; | |
... | |
} | |
} |
这里的原理相当于编译器进行了字符串替换,并且上文中 .cent
的内容也被原样编译到了 CSS 中,这时我们不想看到的
解决方法就是把 .cent
改为 .cent()
,这样 CSS 就不会编译.cent
- 我们称
.cent
的写法为普通混合,混合也会被编译到 css 文件中
# 不带参数混合
- 我们称
.cent()
的写法为不带参数混合,混合不会被编译到 css 文件中
# 带参数的混合
我们希望我们的混合可以提供一个 API, 例如我们像做一个居中后偏左 x 个 px 的一个混合,我们可以这样定义这个混合
.cont-left(@off-set){ | |
margin:0 auto; | |
transform: translateX(-@off-set); | |
} | |
div{ | |
... | |
.cont-left(10px) | |
} |
这样我们调用混合的时候输入 10px 就会居中,左移 10px, 看起来有点像函数,但是就是叫做混合
- 我们称
.cont-left(@off-set)
的写法为带参数的混合,混合不会被编译
# 带默认参数的混合
带参数的混合接受默认参数
.my_mixin1(@a,@b,@c){ | |
} | |
div{ | |
my_mixin1(); | |
my_mixin1(1px); | |
} |
如上,两种调用都是非法的,必须是形残和实参数目相同,当然可以设置默认值
.my_mixin1(@a,@b:1px,@c:2px){ | |
} | |
div{ | |
my_mixin1(); | |
my_mixin1(5px); | |
my_mixin1(5px,6px); | |
my_mixin1(5px,6px,7px); | |
} |
我们给 @b
与 @c
默认值为 1 和 2, @a
没给,所以第一个调用非法,第二个把 5 给了 @a
, 第三个 a=5,b=6,c=2
,第四个直接分配,其冲突处理规则与 C 语言的默认参数处理规则相同,也可以在调用的时候制定赋值给的参数,与 C 语言相同
- 以上我们称之为带默认参数的混合
# 命名参数匹配
.my_mixin1(@a,@b:1px,@c:2px){ | |
} | |
div{ | |
my_mixin1(@a:5px,@c:6px); | |
} |
得到 a=5,b=1,c=2
- 以上我们称之为命名参数匹配
# 匹配模式
我们希望实现同一个功能,但是有略有差别,我们希望传的参数尽可能少。类似于 C++ 中的多态
mixin_com(){ | |
... // sth common | |
} | |
mixin(L,@a,@b){ | |
.mixin_com(); | |
... // sth special | |
} | |
mixin(R,@a,@b){ | |
.mixin_com(); | |
... // sth special | |
} | |
div{ | |
mixin(L,1,1); | |
mixin(R,1,1) | |
} |
可以继续优化我们的写法,使用同名无匹配模式开头为 @_
可以实现在调用任何一个多态的时候顺便调用他
mixin(@_){ | |
... // sth common | |
} | |
mixin(L,@a,@b){ | |
... // sth special | |
} | |
mixin(R,@a,@b){ | |
... // sth special | |
} | |
div{ | |
mixin(L,1,1); | |
mixin(R,1,1) | |
} |
当然, @_
后面可以加参数,如下代码,我们可以把 @_
理解为占位符
.mixin(S,@h,@w,@c){ | |
border:solid; | |
} | |
.mixin(D,@h,@w,@c){ | |
border:double; | |
} | |
.mixin(@_,@h,@w,@c){ | |
width: @w; | |
height: @h; | |
background-color: @c; | |
border-width: 20px; | |
} | |
div{ | |
.mixin(D,100px,100px,#bfa) | |
} |
# Arguments 变量
类似于 Python 的列表传参,带白哦全体实参列表
.myb(@1,@2,@3){ | |
border: @arguments; | |
} | |
div{ | |
.myb(1px,solid,red) | |
} |
# Less 的计算
div{ | |
width:(100px+100); | |
} |
以上计算是可以的,只需要计算双方一方有单位即可
# Less 的继承
在写 less 过程中,如果写成
.mixin(){ | |
... | |
} | |
div1{ | |
.mixin(); | |
... | |
} | |
div2{ | |
.mixin(); | |
... | |
} |
编译的结果将会是
div1{ | |
... // .mixin()的全文复制下来 | |
... | |
} | |
div2{ | |
... // .mixin()的全文复制下来 | |
... | |
} |
这样 .mixin
内容被复制了两次,是一种低效的写法,如果编译为如下就更好了
div1,div2{ | |
... // .mixin()的全文复制下来 | |
} | |
div1{ | |
... | |
} | |
div2{ | |
... | |
} |
想要实现如上的效果需要将 less 写成继承的形式
.mixin(){ | |
... | |
} | |
div1:extend(.mixin){ | |
... | |
} | |
div2:extend(.mixin){ | |
... | |
} |
明显可以看出继承的效率比混合高,但是灵活性差,不能传递参数
在编译过程中,内部处理很简单
- 找到相同
extend
的选择器 - 用
,
隔开,写在一起 - 应用 extend 的样式
更优秀的代码风格应该是
.mixin(){ | |
... | |
} | |
div1{ | |
&:extend(.mixin) | |
... | |
} | |
div2{ | |
&:extend(.mixin) | |
... | |
} |
但存在问题,如果代码写成如下
.mixin(){ | |
... | |
} | |
.mixin:hover(){ | |
... | |
} | |
div1{ | |
&:extend(.mixin) | |
... | |
} | |
div2{ | |
&:extend(.mixin) | |
... | |
} |
两个 div 是不继承 hover
的属性的,只需加上一个 all
表示全部继承
.mixin(){ | |
... | |
} | |
.mixin:hover(){ | |
... | |
} | |
div1{ | |
&:extend(.mixin all) | |
... | |
} | |
div2{ | |
&:extend(.mixin all) | |
... | |
} |
# 5. 避免编译
我们如果写下面的 Less 代码
*{ | |
margin: 10*100px; | |
padding: cacl(10*100px); | |
} |
编译之后是
*{ | |
margin: 1000px; | |
padding: cacl(1000px); | |
} |
cacl()
是 css 的计算函数,但是被 less 给算了,我们不想让 less 做,希望编译成如下样式
*{ | |
margin: 1000px; | |
padding: cacl(10*100px); | |
} |
也就是让 10*100px
避免编译,要求原样输出,只要把需要的部分加上 ~""
, 也就是
*{ | |
margin: 10*100px; | |
padding: ~"cacl(10*100px)"; | |
} |
p.s. IE6 有一个与 BFC 类似的模式,一旦出现兼容性问题首先考虑开启他,放法是 overflow:hidden