此篇延續 Bootstrap 客製化 Sass utilities(上)最後尚未介紹的 generate-utility,解析 generate-utility 是如何生成通用類別樣式。
generate-utility 來自於
mixins/_utilities.scss
這隻主要生成通用類別樣式的檔案。
主要分為三個區塊來解析
取得 utilities 資料中 values 的值,並透過迴圈讀取出來,若
$values
不是 map 型態,則會將其轉換為 list 型態(為了讓最後生成通用類別樣式時可以取得到 key, value)。
@mixin generate-utility($utility, $infix, $is-rfs-media-query: false) {
$values: map-get($utility, values);
@if type-of($values) == "string" or type-of(nth($values, 1)) != "list" {
$values: zip($values, $values);
}
}
$values
內的 api 設置參數。@each $key, $value in $values {
}
property
為要產生的 css 屬性名稱,型態為字串或陣列。
判斷型態是否為字串:
$properties
的方式進行,因此若型態為字串(只有一個屬性),則透過append 將 property 值插入到空白陣列中。@if type-of($properties) == "string" {
$properties: append((), $properties);
}
$property-class
css 屬性對應的通用類別名稱。(ex:font-size
對應fs
)
判斷參數中是否有設置 class 參數
若 $property-class
值為 null 則賦予空字串。
$property-class: if(map-has-key($utility, class), map-get($utility, class), nth($properties, 1));
$property-class: if($property-class == null, "", $property-class);
偽類 Pseudo-classes 參數。(ex:
:hover
、:focus
)
若 $property-class
值為 null 則賦予空陣列, @each
遇到空置列則不會執行回圈。
$state: if(map-has-key($utility, state), map-get($utility, state), ());
沒看到 Bootstrap 原始碼使用到,但看了一下生成通用類別的方法,想到了有趣的靈感。
state 使用特性:
:state 名稱
。(ex::hover
)利用 state 特性,來針對某個 css 屬性,設置對應的偽類樣式。
舉例滑鼠移過 container-fluid
元素時就改變背景顏色。
"container-fluid-hover": (
property: background-color,
state: hover,
class: container-fluid,
values: (
"index": $dark;
"product": $light;
)
),
編譯後的樣式
.container-fluid-*hover
樣式就有 hover 效果了。.container-fluid-index-hover:hover {
background-color: $dark
}
.container-fluid-product-hover:hover {
background-color: $light
}
優勢:
注意兩個前提:
若不符合上述前提,就沒有達到 縮短程式碼
這個目的,其實直接把偽類樣式寫在原本樣式的後方即可。
判斷有取得斷點的且
$property-class
為""
的情況下,就將$infix
前方的-
符號拿掉後並覆蓋$infix
值。
$infix: if($property-class == "" and str-slice($infix, 1, 1) == "-", str-slice($infix, 2), $infix);
判斷若
$value
的 key 值等於 null,則不加通用類別前綴字。
舉例 border
border
border-0
通常用來作為 css 屬性的預設樣式。(ex:border、rounded、shadow)
$property-class-modifier: if($key, if($property-class == "" and $infix == "", "", "-") + $key, "");
判斷是否有設置響應式,隨著視窗大小計算適合的尺寸。(這邊先跳過,之後有緣再來寫一篇 rfs 計算方式)
@if map-get($utility, rfs) {
@if $is-rfs-media-query {
$val: rfs-value($value);
$value: if($val == rfs-fluid-value($value), null, $val);
}
@else {
$value: rfs-fluid-value($value);
}
}
將以上取得的參數,組合起來產生通用類別的樣式。
生成的通用類別分為兩種:
兩種差別在於,是否有設置 state 偽類參數。
$property-class:通用類別前綴字。
$infix:斷點 point。
$property-class-modifier:通用類別 values
參數的 key 值。
$properties: 要執行的 css 屬性。
$value:通用類別 values 參數的 value 值。
$enable-important-utilities:是否在生成通用類別樣式後方加上 !important(預設是 true)。
.#{$property-class + $infix + $property-class-modifier} {
@each $property in $properties {
#{$property}: $value if($enable-important-utilities, !important, null);
}
}
兩種生成樣式後的對照圖
一般通用類別:
含偽類通用類別:
小技巧:
拿掉
,只需移除 -#{$pseudo}
即可。將修改 BS5 的核心 code 簡單刻了兩個版本 CodePen 連結: