混合(Mixins)

混入和函数定义方法一致,但是应用却大相径庭。

例如,下面有定义的border-radius(n)方法,其却作为一个 mixin(如,作为状态调用,而非表达式)调用。

border-radius()选择器中调用时候,属性会被扩展并复制在选择器中。

border-radius(n)
  -webkit-border-radius n
  -moz-border-radius n
  border-radius n

form input[type=button]
  border-radius(5px)

编译为:

form input[type=button] {
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
}

使用混入书写,你可以完全忽略括号,提供梦幻般私有属性的支持。

border-radius(n)
  -webkit-border-radius n
  -moz-border-radius n
  border-radius n

form input[type=button]
  border-radius 5px

注意到我们混合书写中的border-radius当作了属性,而不是一个递归函数调用。

更进一步,我们可以利用arguments这个局部变量,传递可以包含多值的表达式:

border-radius()
  -webkit-border-radius arguments
  -moz-border-radius arguments
  border-radius arguments

现在,我们可以像这样子传值: border-radius 1px 2px / 3px 4px!

另外我们可以使用插值 {param}:

  border(side, args...)
    if side
      border-{side}  args
    else
      border args

  .border-thick
    border('left' , 10px, 'darkred')

  .border
    border('' , 1px, 'darkred')

渲染为:

  .border-thick {
    border-left: 10px 'darkred';
  }
  .border {
    border: 1px 'darkred';
  }

另外一个很赞的应用是特定的私有前缀支持——例如IE浏览器的透明度(opacity):

    support-for-ie ?= true

    opacity(n)
      opacity n
      if support-for-ie
        filter unquote('progid:DXImageTransform.Microsoft.Alpha(Opacity=' + round(n * 100) + ')')

    #logo
      &:hover
        opacity 0.5

渲染为:

    #logo:hover {
      opacity: 0.5;
      filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
    }

父级引用

混合书写可以利用父级引用字符&, 继承父业而不是自己筑巢。

例如,我们要用stripe(even, odd)创建一个条纹表格。evenodd均提供了默认颜色值,每行也指定了background-color属性。我们可以在tr嵌套中使用&来引用tr,以提供even颜色。

 stripe(even = #fff, odd = #eee)
   tr
     background-color odd
     &.even
     &:nth-child(even)
       background-color even

然后,利用混合书写,如下:

 table
   stripe()
   td
     padding 4px 10px

 table#users
   stripe(#303030, #494848)
   td
     color white

另外,stripe()的定义无需父引用:

stripe(even = #fff, odd = #eee)
  tr
    background-color odd
  tr.even
  tr:nth-child(even)
    background-color even

如果你愿意,你可以把stripe()当作属性调用:

stripe #fff #000

Block mixins

You can pass blocks to mixins by calling mixin with + prefix:

+foo()
  width: 10px

The passed block would be available inside the mixin as block variable, that then could be used with interpolation:

foo()
  .bar
    {block}

+foo()
  width: 10px

=> .bar {
     width: 10px;
   }

This feature is in its rough state ATM, but would be enhanced in the future.

混合中的混合

自然,混合可以利用其它混合,建立在它们自己的属性和选择器上。

例如,下面我们创建内联comma-list()(通过inline-list())以及逗号分隔的无序列表。

 inline-list()
   li
     display inline

 comma-list()
   inline-list()
   li
     &:after
       content ', '
     &:last-child:after
       content ''

 ul
   comma-list()

渲染为:

ul li:after {
  content: ", ";
}
ul li:last-child:after {
  content: "";
}
ul li {
  display: inline;
}