Stylus官方文档

为什么用Stylus?

Stylus很多在原始CSS之外的增强功能。

如:

  • 简写CSS
  • 支持变量
  • 支持函数
  • 支持嵌套

……

等等。

下面详细了解一下Stylus的特性。

安装

全局安装:

npm install stylus -g

Stylus特性

  • 冒号可有可无
  • 分号可有可无
  • 逗号可有可无
  • 括号可有可无
  • 变量
  • 插值(Interpolation)
  • 混合(Mixin)
  • 数学计算
  • 强制类型转换
  • 动态引入
  • 条件表达式
  • 迭代
  • 嵌套选择器
  • 父级引用
  • Variable function calls
  • 词法作用域
  • 内置函数(超过 60 个)
  • 语法内函数(In-language functions)
  • 压缩可选
  • 图像内联可选
  • Stylus 可执行程序
  • 健壮的错误报告
  • 单行和多行注释
  • CSS 字面量
  • 字符转义
  • TextMate 捆绑
  • 以及更多!

语法

变量

可以将表达式赋值给变量,然后在整个样式表中使用变量:

 font-size = 14px

 body
   font font-size Arial, sans-serif

编译为:

 body {
   font: 14px Arial, sans-serif;
 }

变量可以包含一个表达式列表

font-size = 14px
font-stack = "Lucida Grande", Arial, sans-serif

body
  font font-size font-stack

编译为:

body {
  font: 14px "Lucida Grande", Arial, sans-serif;
}

标识符(变量名,函数等)还可以包含 $ 字符。例如:

$font-size = 14px
body {
  font: $font-size sans-serif;
}

函数

Stylus 具有强大的内置于语言层面的函数定义。函数定义与混入(mixins)一致,但是却可以返回值。

返回值
一个很简单的例子:创建一个两数相加的函数。

add(a, b)
  a + b

我们可以将上述函数用在条件表达式中、作为属性值等等。

 body 
   padding add(10px, 5)

输出为:

 body {
   padding: 15px;
 }

默认参数
可选参数可以赋值一个表达式。在 Stylus 中,我们甚至可以使用参数列表中左侧的参数为右侧参数赋予默认值!

例如:

 add(a, b = a)
   a + b

 add(10, 5)
 // => 15
 
 add(10)
 // => 20

注意: 因为参数默认是赋值,因此我们可以使用函数调用作为默认值:

 add(a, b = unit(a, px))
   a + b

命名参数
函数可以接受命名参数。这可以免去记忆参数顺序的麻烦,或者说是提供了代码的可读性。

例如:

subtract(a, b)
  a - b

subtract(b: 10, a: 25)

函数体
我们把 add() 函数做进一步的扩展。通过内置 unit() 函数把所有参数的数值单位都变成 px。因为它为每个参数重新赋值了,并且每个参数都提供了字符串标识数值单位类型,因此,可以无视单位换算的内部机制。

 add(a, b = a)
   a = unit(a, px)
   b = unit(b, px)
   a + b

 add(15%, 10deg)
 // => 25

多个返回值
Stylus 函数可以返回多个值,就像你给一个变量赋予多个值一样。

例如,下面就是一个有效的赋值:

   sizes = 15px 10px
 
   sizes[0]
   // => 15px 

类似的,我们可以在函数中返回多个值:

   sizes()
     15px 10px

   sizes()[0]
   // => 15px

当返回值是标识符时是个小小的例外。例如,下面的代码对于 Stylus 来说看上去好像一个属性赋值(但是没有赋值操作符):

 swap(a, b)
   b a

为避免歧义,我们可以使用括号,或是 return 关键字:

  swap(a, b)
    (b a)

  swap(a, b)
    return b a

条件
假设我们想要创建一个名为 stringish() 的函数,用来决定参数是否可以转换为字符串。我们检查 val 是否是字符串或缩进(类似字符)。由于未定义的标识符将其自身作为值,因此我们就可以像下面一样对其自身进行比较(使用 yes 和 no 代替 true 和 false):

 stringish(val)
   if val is a 'string' or val is a 'ident'
     yes
   else
     no

用法:

 stringish('yay') == yes
 // => true
   
 stringish(yay) == yes
 // => true
   
 stringish(0) == no
 // => true

注意: yes 和 no 并不是布尔字面量(boolean literals)。他们在这里只是简单的未定义标识符。

另外一个例子:

compare(a, b)
  if a > b
    higher
  else if a < b
    lower
  else
    equal

用法:

compare(5, 2)
// => higher

compare(1, 5)
// => lower

compare(10, 10)
// => equal

别名
将函数名赋值给一个新的标识符就为其创建了一个别名。例如,我们前面定义的 add() 函数就可以起一个别名叫做 plus(),如下所示:

  plus = add
  
  plus(1, 2)
  // => 3

函数作为变量使用
与为函数起 “别名” 一样,我们可以将函数作为参数传递。如下, invoke() 函数能够接收一个函数作为参数,因此我们可以将 add() 或 sub() 函数作为参数传递给 invoke()。

add(a, b)
  a + b

sub(a, b)
  a - b

invoke(a, b, fn)
  fn(a, b)

body
  padding invoke(5, 10, add)
  padding invoke(5, 10, sub)

生成:

body {
  padding: 15;
  padding: -5;
}

匿名函数
利用 @(){} 语法可以在需要的地方使用匿名函数。下面展示了如何利用匿名函数创建一个自定义的 sort() 函数:

sort(list, fn = null)
  // default sort function
  if fn == null
    fn = @(a, b) {
      a > b
    }

  // bubble sort
  for $i in 1..length(list) - 1
    for $j in 0..$i - 1
      if fn(list[$j], list[$i])
        $temp = list[$i]
        list[$i] = list[$j]
        list[$j] = $temp
  return list

  sort('e' 'c' 'f' 'a' 'b' 'd')
  // => 'a' 'b' 'c' 'd' 'e' 'f'

  sort(5 3 6 1 2 4, @(a, b){
    a < b
  })
  // => 6 5 4 3 2 1

参数
arguments 是所有函数体都能够访问的局部变量,包含了传递过来的所有参数。

例如:

 sum()
   n = 0
   for num in arguments
     n = n + num

 sum(1,2,3,4,5)
 // => 15

Hash 实例
下面我们定义了 get(hash, key) 函数,返回 key 的值或 null。我们遍历 hash 中的每个键值对(pair),如果键(key)相匹配则返回对应的值。

  get(hash, key)
    return pair[1] if pair[0] == key for pair in hash

如下所示,语言内置的函数功能和 Stylus 表达式相结合,能够提供强大的灵活性:

  hash = (one 1) (two 2) (three 3)
  
  get(hash, two)
  // => 2

  get(hash, three)
  // => 3

  get(hash, something)
  // => null

关键字参数

Stylus 支持关键字参数或 “kwargs”。这样就能够通过其关联的参数名来引用参数。

以下示例在功能上是等价的。 然而,我们可以 在参数列表中的任何位置放置关键字参数。 未 设置关键字的参数将被用来填充其余尚未填充的参数。

  body {
    color: rgba(255, 200, 100, 0.5);
    color: rgba(red: 255, green: 200, blue: 100, alpha: 0.5);
    color: rgba(alpha: 0.5, blue: 100, red: 255, 200);
    color: rgba(alpha: 0.5, blue: 100, 255, 200);
  }

转换为:

   body {
     color: rgba(255,200,100,0.5);
     color: rgba(255,200,100,0.5);
     color: rgba(255,200,100,0.5);
     color: rgba(255,200,100,0.5);
   }

若要查看函数或混合(mixin)所能接受的参数,请使用 p() 函数:

p(rgba)

输出:

inspect: rgba(red, green, blue, alpha)

注释

Stylus 支持三种注释方式:单行注释、多行注释和多行缓冲注释。

单行注释
单行注释和 JavaScript 中的注释方式一样,不会输出到最终的 CSS 中:

// I'm a comment!
body
  padding 5px // some awesome padding

多行注释
多行注释看起来有点像 CSS 的常规注释。然而,它们只有在 compress 选项未启用的时候才会被输出。

/*
 * Adds the given numbers together.
 */

add(a, b)
  a + b

多行缓冲注释
以 /*! 开头的多行注释将被输出。这其实是告诉 Stylus 无论是否压缩(开启 compress 选项)都直接输出此注释。

/*!
 * Adds the given numbers together.
 */

add(a, b)
  a + b