Less初探 - guananddu/gTools GitHub Wiki

前言

Less翻译来就是较少、减少的意思,可以看出Less作者的理念就是Less is more,减少重复代码,提供更多特性,但是最终目的都是写出更好的css。


关于作者

Alexis Sellier (需要使用翻墙代理)


中文站点

LESS


使用方法

1,按照官网说的,引用less.js; 2,部署前编译,更多工具在这里


特性小览

变量

less:

/*变量定义使用@符号*/
@nice-blue: #5B83AD;
/*变量还能计算*/
@light-blue: @nice-blue + #111;

#header { color: @light-blue; }

output:

/*计算后的颜色值*/
#header { color: #6c94be; }

需要注意:LESS 中的变量为完全的 ‘常量’ ,所以只能定义一次


混合

混合也许是Less中最常用的特性,能够有效地减少一些公用css样式属性的书写次数,还是来看例子,才能更好地理解它:

普通混合(不带参数)

less:

/*在Less中定义的一个样式class,没有带参数哦*/
.bordered {
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}

#menu a {
  color: #111;
  /*这样来使用*/
  .bordered;
}
.post a {
  color: red;
  /*这样来使用*/
  .bordered;
}

output:

/*!!!亲,我还会原样输出!!!*/
.bordered {
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}
#menu a {
  color: #111;
  /*bordered说:我还在这里*/
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}
.post a {
  color: red;
  /*bordered说:我还在这里*/
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}

更为奇妙的是:任何 CSS class, id 或者 元素 属性集都可以以同样的方式引入


高级混合(带参数,似少林而非少林,似函数而非函数,:P)

less:

/*定义带参数的混合,默认值是5px,亲,output中你就看不到我了*/
.border-radius (@radius: 5px) {
  border-radius: @radius;
  -moz-border-radius: @radius;
  -webkit-border-radius: @radius;
}

#header1 {
  /*使用默认值*/
  .border-radius;  
}

#header2 {
  /*使用自定义值*/
  .border-radius(4px);
}

output:

#header1 {
  /*使用默认值*/
  border-radius: 5px;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
}

#header2 {
  /*使用自定义值*/
  border-radius: 4px;
  -moz-border-radius: 4px;
  -webkit-border-radius: 4px;
}

有个小技巧:你也可以定义不带参数属性集合,如果你想隐藏这个属性集合,不让它暴露到CSS中去,但是你还想在其他的属性集合中引用,你会发现下面这个方法非常的好用:

less:

/*定义混合的时候,只有小括号,而没有参数列表*/
/*这样就隐藏了.wrap*/
.wrap () {
  text-wrap: wrap;
  white-space: pre-wrap;
  white-space: -moz-pre-wrap;
  word-wrap: break-word;
}

pre { .wrap }

output:

pre {
  text-wrap: wrap;
  white-space: pre-wrap;
  white-space: -moz-pre-wrap;
  word-wrap: break-word;
}

在混合中,你可以看到熟悉的"arguments"变量:

less:

/*参数列表太长的时候,使用arguments“局部变量”可以省去很多笔墨*/
.box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #000) {
  box-shadow: @arguments;
  -moz-box-shadow: @arguments;
  -webkit-box-shadow: @arguments;
}
/*使用的时候,可以只给前两个自定义值,后面的参数使用默认值*/
.box-shadow(2px, 5px);

output:

box-shadow: 2px 5px 1px #000;
-moz-box-shadow: 2px 5px 1px #000;
-webkit-box-shadow: 2px 5px 1px #000;

更高级混合 - -!!! 混合中的模式匹配和导引表达式
Switch型的模式匹配

有的时候,我们想根据不同的传入参数,来使一个混合呈现不同的样式,这种情况怎么办呢?Less可以处理,如下的需求(伪代码,仅为来解释需求):

/*定义了一个混合*/
.mixin (@s, @color) { ... }

/*我想根据@switch的值,来改变不同的@color*/
.class {
  .mixin(@switch, #888);
}

我们可以定义多个.mixin来实现类似于程序设计中switch case的逻辑:

less:

/*第一个参数是'dark'的情况下*/
.mixin (dark, @color) {
  /*调用darken颜色处理函数,下面会有介绍*/
  color: darken(@color, 10%);
}

/*第一个参数是'light'的情况下*/
.mixin (light, @color) {
  /*调用lighten颜色处理函数,下面会有介绍*/
  color: lighten(@color, 10%);
}

/*这就是传说中的default情况*/
.mixin (@_, @color) {
  display: block;
}

/*定义变量*/
@switch: light;

.class {
  /*调用混合*/
  .mixin(@switch, #888);
}

output:

.class {
  /*这里的color值,是调用lighten(@color, 10%)函数之后的颜色值*/
  color: #a2a2a2;
  /*默认的混合样式属性,display:block;*/
  display: block;
}
“重载”型的模式匹配

还可以通过参数个数来进行混合的模式匹配:

less:

/*定义混合*/
.mixin (@a) {
  color: @a;
}
.mixin (@a, @b) {
  color: fade(@a, @b);
}

.color1 {
  .mixin(#000);
}
.color2 {
  .mixin(#000, 40%);
}

output:

.color1 {
  color: #000000;
}
.color2 {
  color: rgba(0, 0, 0, 0.4);
}

混合中的导引

使用导引,可以实现混合中的类似于if/else的条件判断:

less:

/*定义混合,在lightness(@a) >= 50%条件满足时候使用此样式*/
/*lightness会返回此颜色值中的lightness通道值,即亮度值,通常为百分数*/
.mixin (@a) when (lightness(@a) >= 50%) {
  background-color: black;
}
/*定义混合,在lightness(@a) < 50%条件满足时候使用此样式*/
.mixin (@a) when (lightness(@a) < 50%) {
  background-color: white;
}
/*所有情况的匹配样式*/
.mixin (@a) {
  color: @a;
}
.class1 { .mixin(#ddd) }
.class2 { .mixin(#555) }

output:

.class1 {
  background-color: black;
  color: #ddd;
}
.class2 {
  background-color: white;
  color: #555;
}

注意的地方:

1,在混合导引中可用的全部比较运算有: > >= = =< <

2,关键字true只表示布尔真值,例如下面两个混合是相同的:

.truth (@a) when (@a) { ... }
.truth (@a) when (@a = true) { ... }

3,除去关键字true以外的值都被视示布尔假:

.class {
  /*上面的两个truth定义,哪个都不会被匹配*/
  .truth(40);
}

4,导引可以无参数,也可以对参数进行比较运算:

@media: mobile;

.mixin (@a) when (@media = mobile) { ... }
.mixin (@a) when (@media = desktop) { ... }

.max (@a, @b) when (@a > @b) { width: @a }
.max (@a, @b) when (@a < @b) { width: @b }

5,如果想基于值的类型进行匹配,我们就可以使用is*函式:

.mixin (@a, @b: 0) when (isnumber(@b)) { ... }
.mixin (@a, @b: black) when (iscolor(@b)) { ... }

常见的检测函数:

iscolor
isnumber
isstring
iskeyword
isurl

6,逻辑判断中的and,or,not:

与(使用关键字and):

.mixin (@a) when (isnumber(@a)) and (@a > 0) { ... }

或(使用,分割序列):(中文官网此处解释有误)

.mixin (@a) when (@a > 10), (@a < -10) { ... }

非(使用关键字not):

.mixin (@b) when not (@b > 0) { ... }

嵌套规则

less:

#header {
  color: black;

  .navigation {
	font-size: 12px;
  }
  .logo {
	width: 300px;
	/*注意这里的&符号,是对#header .logo:hover的伪类定义*/
	&:hover { text-decoration: none }
  }
}

output:

#header {
  color: black;
}
#header .navigation {
  font-size: 12px;
}
#header .logo {
  width: 300px;
}
#header .logo:hover {
  text-decoration: none;
}

再看&:

less:

.bordered {
  &.float {
	float: left; 
  }
  .top {
	margin: 5px; 
  }
}

output:

.bordered.float {
  float: left;  
}
.bordered .top {
  margin: 5px;
}

运算

任何数字、颜色或者变量都可以参与运算:

@base: 5%;
@filler: @base * 2;
@other: @base + @filler;

color: #888 / 4;
background-color: @base-color + #111;
height: 100% / 2 + @filler;

关于运算更多的信息,参看官网介绍。


Color操作函数

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

saturate(@color, 10%);    // return a color 10% *more* saturated than @color
desaturate(@color, 10%);  // return a color 10% *less* saturated than @color

fadein(@color, 10%);      // return a color 10% *less* transparent than @color
fadeout(@color, 10%);     // return a color 10% *more* transparent than @color
fade(@color, 50%);        // return @color with 50% transparency

spin(@color, 10);         // return a color with a 10 degree larger in hue than @color
spin(@color, -10);        // return a color with a 10 degree smaller hue than @color

mix(@color1, @color2);    // return a mix of @color1 and @color2

如何使用,见下边:

@base: #f04615;

.class {
  color: saturate(@base, 5%);
  background-color: lighten(spin(@base, 8), 25%);
}

这里不再赘述。~~


Math函数

round(1.67); // returns `2`
ceil(2.4);   // returns `3`
floor(2.6);  // returns `2`
percentage(0.5); // returns `50%`

命名空间

有时候,可能为了更好组织CSS或者单纯是为了更好的封装,将一些变量或者混合模块打包起来, 可以像下面这样在#bundle中定义一些属性集之后可以重复使用:

less:

/*顶级命名空间*/
#bundle {
  /*button的样式空间,定义了一个混合*/
  .button () {
	display: block;
	border: 1px solid black;
	background-color: grey;
	&:hover { background-color: white }
  }
  /*tab样式空间*/
  .tab { ... }
  /*citation样式空间*/
  .citation { ... }
}

/*这样使用*/
#header a {
  color: orange;
  /*使用bundle中的button样式集合*/
  #bundle > .button;
}

output:

#header a {
  color: orange;
  display: block;
  border: 1px solid black;
  background-color: grey;
}
#header a:hover {
  background-color: #ffffff;
}

作用域

Less中的作用域类似于“块级”作用域,当此“块”中没有找到,会向上一级“块”查找:

@var: red;

#page {
  @var: white;
  #header {
	color: @var; // white
  }
}

#footer {
  color: @var; // red  
}

注释

1,css形式的注释,编译后css文件中可以保留:

/* Hello, I'm a CSS-style comment */
.class { color: black }

2,双斜线注释,编译后css中去除:

// Hi, I'm a silent comment, I won't show up in your CSS
.class { color: white }

导入文件(Importing)

1,导入less文件:

@import "lib.less";
@import "lib";

2,导入css文件(Less不会对它进行处理):

@import "lib.css";

字符串插值

@base-url: "http://assets.fnord.com";
background-image: url("@{base-url}/images/bg.png");

避免编译

当我们再写Less不认识的专用语法的时候,使用~符号,可以让Less略去此语句,保持原状而不去处理,例如:

less:

.class {
  filter: ~"ms:alwaysHasItsOwnSyntax.For.Stuff()";
}

output:

.class {
  filter: ms:alwaysHasItsOwnSyntax.For.Stuff();
}

需要将要避免编译的值用 “”包含起来


使用Javascript表达式

简易例子:

less:

@var: `"hello".toUpperCase() + '!'`;

output:

@var: "HELLO!";

混搭字符串插值和避免编译:

less:

@str: "hello";
@var: ~`"@{str}".toUpperCase() + '!'`;

output:

@var: HELLO!;

访问Javascript运行环境:

@height: `document.body.clientHeight`;

配合使用color函数:

@color: color(`window.colors.baseColor`);
@darkcolor: darken(@color, 10%);

更多特性详细,请参看中文站点~~ :)