Sass - 混合

混合(Mixins)

Mixins 的作用很像函式(function),主要用於重複使用的樣式區塊或產出具有變化性的樣式效果,它與函式一樣可以透過參數傳遞變數,mixins 是 Sass 很重要的功能。

使用時機

由於 Mixins 太好用了,一不小心可能會過度使用。大量的重複使用可能會讓樣式碼太過肥大,導致加載變慢。

  • 當不停地重複一段樣式,就可以考慮使用 Mixins。

使用 Mixins

  • 使用 @mixin @mixin name() { css 樣式 } ,定義一個「 混合 」。
  • 使用 @include name,引用一個「 混合 」。
  • @include 可以存在於選擇器內、外,只要寫法允許。
  • @mixin 沒有參數時可以不用 (),引用 @include 也可以不用()。
  • 可同時引用多個「混合」。

@mixin 與 @extend 的差異

@mixin 與 @extend 皆可達到減少撰寫重複程式碼的目的,那怎麼選擇呢?

  • @mixin: 可以將一段樣式碼寫入 class 內,且可使用變數。
  • @extend: 將樣式獨立出來,不可使用變數。

基本上 @extend 是將 CSS 集中,所以程式碼較少,相反的,@mixin 則是寫一次就多產生一次 CSS,所以程式碼較多,較簡單的分辨方法式如果需使用變數就使用 @mixin,不需要則使用 @extend,
不過 @extend 會將相同的樣式獨立出來以群組選擇器集合在一起,@mixin 則不會,所以在選擇器內使用一包 @mixin 就等同使用一大段樣式碼,在另一個選擇器使用則是另一大包樣式碼,需謹慎使用。

@mixin color() {
background: blue;
}

body {
@include color();
}

@mixin link() {
a {
color: blue;
background-color: red;
}
}
@include link();

傳遞參數(Arguments)

  • 單一參數
@mixin bgcolor($bgcolor) {
background: $bgcolor;
}

body {
@include bgcolor(#ffa);
}
  • 多參數
@mixin text($size, $lin-height, $weight, $color) {
font-size: $size;
line-height: $line-height;
font-weight: $weight;
color: $color;
}

傳遞參數須注意事項

傳遞參數可使用數字,在 mixins 區塊的單位可使用插值語法表示。

#{$變數名稱}單位

@mixin rotate($deg) {
transform: rotate(#{$deg}deg);
}

.box {
@include rotate(45);
}

參數若不需要不能省略

如果省略參數不寫,Sass 編譯會錯誤!非必要的參數要用 null,告訴 Sass 數值可為 null。

@mixin text($size, $lin-height: null, $weight: null, $color: null) {
font-size: $size;
line-height: $line-height;
font-weight: $weight;
color: $color;
}
h1 {
@include text(2em);
}
h1 {
@include text(1.25em, 1.2);
}
p {
@include text(1em, 1.2, normal);
}

參數可以使用預設數值

// scss
@mixin sexy-border($color, $width: 1in) {
border: {
color: $color;
width: $width;
style: dashed;
}
}
p {
@include sexy-border(blue);
}
h1 {
@include sexy-border(blue, 2in);
}
// css
p {
border-color: blue;
border-width: 1in;
border-style: dashed;
}

h1 {
border-color: blue;
border-width: 2in;
border-style: dashed;
}

直接指定給參數一個值

這種方式也叫關鍵詞參數,閱讀起來會很方便,提供明確易懂的接口。

p {
@include sexy-border($color: blue);
}
h1 {
@include sexy-border($color: blue, $width: 2in);
}

不確定多少個參數,可以使用 …

有時,不能確定混合指令需要使用多少個參數,比如一個關於 box-shadow 的混合不能確定有多少個 shadow 會被用到。這時可以使用「…」表示(寫在參數的最後方)告訴 Sass 將這些參數視為陣列處理:

// scss
@mixin box-shadow($shadows...) {
box-shadow: $shadows;
}
.shadows {
@include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
}

// css
.shadows {
box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
}

使用一串變數值,也可以使用…

同樣地,傳陣列進去,如果沒使用…,Sass 會報錯。

// scss
@mixin colors($text, $background, $border) {
color: $text;
background-color: $background;
border-color: $border;
}
// 一串變數值 ...
$values: #ff0000, #00ff00, #0000ff;
.primary {
@include colors($values...);
}
// css
.primary {
color: #ff0000;
background-color: #00ff00;
border-color: #0000ff;
}

混合可以包含混合

@mixin compound {
@include highlighted-background;
@include header-text;
}
@mixin highlighted-background {
background-color: #fc0;
}
@mixin header-text {
font-size: 20px;
}

@content

在使用 @mixin 時搭配 @content 可以把 @include 中的內容載入,這很適合用在 RWD 的 media-query 使用:

// scss
@mixin sm {
@media (min-width: 576px) {
@content;
}
}

@mixin md {
@media (min-width: 768px) {
@content;
}
}

@mixin lg {
@media (min-width: 992px) {
@content;
}
}

@mixin xl {
@media (min-width: 1200px) {
@content;
}
}

@include sm {
#logo {
font-size: 1.5rem;
}
}
// css
@media (min-width: 576px) {
#logo {
font-size: 1.5rem;
}
}