跳到內容
在此頁面

混合

混合和函式以相同的方式定義,但它們的應用方式不同。

例如,我們在下方定義了一個 border-radius(n) 函式,它作為一個混合被呼叫(亦即,作為一個陳述式被呼叫,而不是作為一個表達式的一部分)。

當在選擇器中呼叫 border-radius() 時,屬性會展開並複製到選擇器中。

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)

編譯為

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

使用混合時,你可以完全省略括號,提供絕佳的透明供應商屬性支援!

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 本地變數,包含傳遞的表達式,允許傳遞多個值

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}

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')

渲染

.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
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);
}
#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
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
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(even = #fff, odd = #eee)
  tr
    background-color odd
  tr.even
  tr:nth-child(even)
    background-color even

如果我們願意,可以呼叫 stripe(),就像它是屬性一樣

stripe #fff #000
stripe #fff #000

區塊混合

你可以透過呼叫帶有 + 前綴的 mixin 來傳遞區塊

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

傳遞的區塊會在 mixin 內部作為 block 變數使用,然後可以使用內插

foo()
  .bar
    {block}

+foo()
  width: 10px

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

+foo()
  width: 10px

=> .bar {
      width: 10px;
    }

此功能目前處於粗略狀態,但將來會進行強化。

在 Mixin 中混合 Mixin

Mixin 可以(當然可以!)使用其他 mixin,建立在它們自己的選擇器和屬性之上。

例如,以下我們建立 comma-list() 來內嵌(透過 inline-list())並以逗號分隔一個無序清單。

inline-list()
  li
    display inline

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

ul
  comma-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;
}
ul li:after {
  content: ", ";
}
ul li:last-child:after {
  content: "";
}
ul li {
  display: inline;
}