Skip to content
On this page

混合器 (mixins)

混合器和函数的定义方式相同,但它们的应用方式不同。

例如,我们在下面定义了一个 border-radius(n) 函数,它被作为_混合器_调用(即,作为语句调用,而不是表达式的一部分)。

当在选择器内调用 border-radius() 时,属性会被展开并复制到选择器中。

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

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

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

编译为:

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

使用混合器时,你可以完全省略括号,提供出色的透明供应商属性支持!

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

form input[type=button]
  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 局部变量,它包含传递的表达式,允许传递多个值:

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

现在我们可以传递如 border-radius 1px 2px / 3px 4px 的值!

我们也可以使用插值 {param}

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

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

.border
  border('' , 1px, 'darkred')
border(side, args...)
  if side
    border-{side}  args
  else
    border args

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

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

渲染为:

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

另一个很好的用途是为供应商特定属性添加透明支持,例如为 IE 提供 opacity 支持:

stylus
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
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

渲染为:

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

父级引用

混合器可以使用父级引用字符 &,作用于父级而不是进一步嵌套。

例如,假设我们想创建一个 stripe(even, odd) 混合器用于条纹化表格行。我们为 evenodd 提供默认颜色值,并在行上分配 background-color 属性。在 tr 内嵌套使用 & 引用 tr,提供 even 颜色。

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

然后我们可以如下所示使用该混合器:

stylus
table
  stripe()
  td
    padding 4px 10px

table#users
  stripe(#303030, #494848)
  td
    color white
table
  stripe()
  td
    padding 4px 10px

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

或者,可以不使用父级引用定义 stripe()

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

如果我们愿意,可以像属性一样调用 stripe()

stylus
stripe #fff #000
stripe #fff #000

块混合器

你可以通过使用 + 前缀调用混合器来传递块:

stylus
+foo()
  width: 10px
+foo()
  width: 10px

传递的块在混合器内部将作为 block 变量可用,然后可以与插值一起使用:

stylus
foo()
  .bar
    {block}

+foo()
  width: 10px

=> .bar {
      width: 10px;
    }
foo()
  .bar
    {block}

+foo()
  width: 10px

=> .bar {
      width: 10px;
    }

此功能目前处于初级状态,但将来会增强。

在混合器中混合其他混合器

混合器当然可以利用其他混合器,构建自己的选择器和属性。

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

stylus
inline-list()
  li
    display inline

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

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

渲染为:

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

Released under the MIT License.