Jade Dungeon

Less

安装

npm

sudo npm install -g less

测试,建立文件styles.less

@base: #f938ab;

.box-shadow(@style, @c) when (iscolor(@c)) {
  -webkit-box-shadow: @style @c;
  box-shadow:         @style @c;
}
.box-shadow(@style, @alpha: 50%) when (isnumber(@alpha)) {
  .box-shadow(@style, rgba(0, 0, 0, @alpha));
}
.box {
  color: saturate(@base, 5%);
  border-color: lighten(@base, 30%);
  div { .box-shadow(0 0 5px, 30%) }
}

编译

参数:

  • -x压缩
  • --clean-css启用clean css进行压缩

编译成css:

lessc styles.less > styles.css

查看结果:

.box {
  color: #fe33ac;
  border-color: #fdcdea;
}
.box div {
  -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
}

Rhino

在1.7版本以前的 less.js 同样包含了 rhino-compatible 版本。

命令行 rhino 版本需要包含以下两个文件:

  • less-rhino-.js - 编译执行,
  • lessc-rhino-.js - 命令行支持

命令行执行编译:

java -jar js.jar -f less-rhino-<version>.js lessc-rhino-<version>.js styles.less styles.css

以上将编译 styles.less 文件并保存为 styles.css 文件。 输出文件的参数是可选的,如果没有指定该参数,less将默认输出到标准输出中(stdout)。

代码中调用

可以像下面这样在代码中调用 Less 编译器(Node 平台)。

var less = require('less');

less.render('.class { width: (1 + 1) }', function (e, css) {
  console.log(css);
});

输出为

.class {
  width: 2;
}

你还可以手动调用分析器(paser)和编译器:

var parser = new(less.Parser);

parser.parse('.class { width: (1 + 1) }', function (err, tree) {
  if (err) {
    return console.error(err)
  }
  console.log(tree.toCSS());
});

可以给编译器传递多个参数:

var parser = new(less.Parser)({
  paths: ['.', './lib'], // Specify search paths for @import directives
  filename: 'style.less' // Specify a filename, for better error messages
});

parser.parse('.class { width: (1 + 1) }', function (e, tree) {
  tree.toCSS({
    // Minify CSS output
    compress: true
  });
});

浏览器中使用

提示

  • 在浏览器上跑 less.js 非常方便开发,但是不推荐用于生产环境。
  • 务必确保在less.js之前加载你的样式表。
  • 如果加载多个.less样式表文件,每个文件都会被单独编译。 因此,一个文件中所定义的任何变量、mixin或命名空间都无法在其它文件中访问。

先写less样式文件:

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

接下来,加载less.js,必须放在head内的script中:

<script src="less.js" type="text/javascript"></script>

也可以用CDN:

<script src="http://cdn.bootcss.com/less.js/1.7.0/less.min.js"></script>

语法

变量

请注意 LESS 中的变量为完全的「常量」 ,所以只能定义一次:

@nice-blue: #5B83AD;
@light-blue: @nice-blue + #111;

#header { color: @light-blue; }

输出:

#header { color: #6c94be; }

甚至可以用变量名定义为变量:

@fnord: "I am fnord.";
@var: 'fnord';
content: @@var;

解析后:

content: "I am fnord.";

混合

任何CSS的class, id或者元素的属性都可以复用,而不用写多遍重复的代码。

例如已经有一个类bordered

.bordered {
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}

其他的类可以直接包含它的属性,不用再重写一遍:

#menu a {
  color: #111;
  .bordered;
}
.post a {
  color: red;
  .bordered;
}

输出结果:

#menu a {
  color: #111;
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}
.post a {
  color: red;
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}

带参数的混合

/* 参数 */
.border-radius (@radius) {
  border-radius:         @radius;
  -moz-border-radius:    @radius;
  -webkit-border-radius: @radius;
}


/* 调用 */
#header { .border-radius(4px); }
.button { .border-radius(6px); }

还可以设置默认值:

.border-radius (@radius: 5px) {
  border-radius:         @radius;
  -moz-border-radius:    @radius;
  -webkit-border-radius: @radius;
}

#header { .border-radius;  }

隐藏无参数样式

带括号但是没有参数,可以防止把这个样式生成到css里:

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

pre { .wrap }

输出:

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

arguments 变量

@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);

输出:

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

模式匹配

定义不同的模式:

.mixin (dark,  @color) { color: darken(@color, 10%);  }
.mixin (light, @color) { color: lighten(@color, 10%); }
.mixin (@_,    @color) { display: block; }

使用时指定要用哪一个:

@switch: light;

.class { .mixin(@switch, #888); }

输出:

.class { color: #a2a2a2; display: block; }

不光参数的值,参数个数也可以用来匹配。如,只有一个参数是匹配第一个, 如果有第二个参数就匹配第二个:

.mixin (@a)     { color: @a; }
.mixin (@a, @b) { color: fade(@a, @b); }

引导

导引中可用的全部比较运算有:>>===<<。 此外,关键字true只表示布尔真值。

.mixin (@a) when (lightness(@a) >= 50%) { background-color: black; }
.mixin (@a) when (lightness(@a) <  50%) { background-color: white; }
.mixin (@a) { color: @a; }

根据参数的值进行匹配,如:

.class1 { .mixin(#ddd) }
.class2 { .mixin(#555) }

就会得到:

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

下面两个混合是相同的:

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

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

.class {
  .truth(40); // Will not match any of the above definitions.
}

导引序列使用逗号,分割,当且仅当所有条件都符合时,才会被视为匹配成功。

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

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

@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 }

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

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

下面就是常见的检测函式:

  • iscolor
  • isnumber
  • isstring
  • iskeyword
  • isurl

如果你想判断一个值是纯数字,还是某个单位量,可以使用下列函式:

  • ispixel
  • ispercentage
  • isem

最后再补充一点,在导引序列中可以使用and关键字实现与条件:

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

使用not关键字实现或条件

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

嵌套规则

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

输出:

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

注意&符号的使用:如果你想写串联选择器,而不是写后代选择器,就可以用到&了。 这点对伪类尤其有用如:hover:focus。例如:

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

会输出

.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;

LESS 的运算已经超出了我们的期望,它能够分辨出颜色和单位。 如果像下面这样单位运算的话:

@var: 1px + 5;         /* LESS 会输出 6px. */

width: (@var + 5) * 2; /* 括号也同样允许使用 */

border: (@width * 2) solid black;  /* 并且可以在复合属性中进行运算 */

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%);
}

你还可以提取颜色信息:

hue(@color);        // returns the `hue` channel of @color
saturation(@color); // returns the `saturation` channel of @color
lightness(@color);  // returns the 'lightness' channel of @color

如果你想在一种颜色的通道上创建另一种颜色,这些函数就显得那么的好用,例如:

@new: hsl(hue(@old), 45%, 90%);

@new将会保持@old的色调,但是具有不同的饱和度和亮度。

Math 函数

LESS提供了一组方便的数学函数,你可以使用它们处理一些数字类型的值:

round(1.67); // returns `2`
ceil(2.4);   // returns `3`
floor(2.6);  // returns `2`

如果你想将一个值转化为百分比,你可以使用percentage函数:

percentage(0.5); // returns `50%`

命名空间

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

#bundle {
  .button () {
    display: block;
    border: 1px solid black;
    background-color: grey;
    &:hover { background-color: white }
  }
  .tab { ... }
  .citation { ... }
}

你只需要在#header a中像这样引入.button

#header a {
  color: orange;
  #bundle > .button;
}

作用域

LESS 中的作用域跟其他编程语言非常类似,首先会从本地查找变量或者混合模块, 如果没找到的话会去父级作用域中查找,直到找到为止:

@var: red;

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

}

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

注释

CSS 形式的注释在 LESS 中是依然保留的:

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

LESS 同样也支持双斜线的注释, 但是编译成 CSS 的时候自动过滤掉:

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

Importing

你可以在main文件中通过下面的形势引入.less文件,.less后缀可带可不带:

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

如果你想导入一个CSS文件而且不想LESS对它进行处理,只需要使用.css后缀就可以:

@import "lib.css";

这样LESS就会跳过它不去处理它.

字符串插值

变量可以用类似ruby和php的方式嵌入到字符串中,像@{name}这样的结构:

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

避免编译

有时候我们需要输出一些不正确的CSS语法或者使用一些 LESS不认识的专有语法。

要输出这样的值我们可以在字符串前加上一个~,例如:

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

我们可以将要避免编译的值用""包含起来,输出结果为:

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

JavaScript 表达式

JavaScript 表达式也可以在.less文件中使用。可以通过反引号的方式使用:

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

输出:

@var: "HELLO!";

注意你也可以同时使用字符串插值和避免编译:

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

输出:

@var: HELLO!;

它也可以访问JavaScript环境:

@height: `document.body.clientHeight`;

如果你想将一个JavaScript字符串解析成16进制的颜色值, 你可以使用 color 函数:

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