Skip to content

Sass 內建模組總覽:七個 sass: 前綴的工具箱

Sass 內建模組總覽

Dart Sass 把所有內建函式整理成 七個模組,用 @use 載入後以命名空間呼叫:

scss
@use "sass:math";
@use "sass:color";

.card {
  width: math.div(100%, 3);
  border-color: color.scale(#2965f1, $lightness: -20%);
}

七個模組

模組職責代表函式
sass:math數字運算div()round()percentage()
sass:color色彩調整scale()adjust()mix()
sass:string字串處理unquote()slice()index()
sass:list清單操作nth()append()join()
sass:map對照表操作get()merge()has-key()
sass:meta反射與檢查type-of()inspect()load-css()
sass:selector選取器操作nest()append()unify()

為什麼要改成模組

早期所有函式都在全域,可以直接寫 lighten($c, 10%)。問題有兩個:

一、容易撞名。 自訂一個 round() 就蓋掉內建的;CSS 未來新增同名函式也會衝突。

二、看不出來源。 一份專案裡的 tint() 到底是內建的、第三方套件的、還是同事寫的?

改成模組之後,math.round()round() 一眼分得出來,也不再互相干擾。

全域函式已被棄用

lighten()darken()percentage() 這些全域寫法還能編譯,但會出現棄用警告,未來會移除。新程式碼一律用模組寫法。

對照表:舊寫法換新寫法

舊的全域函式現在的寫法
percentage($x)math.percentage($x)
round($x)math.round($x)
$a / $bmath.div($a, $b)
lighten($c, 10%)color.scale($c, $lightness: 10%)
darken($c, 10%)color.scale($c, $lightness: -10%)
map-get($m, $k)map.get($m, $k)
nth($l, 1)list.nth($l, 1)
type-of($x)meta.type-of($x)
str-slice($s, 1, 3)string.slice($s, 1, 3)

lighten 不只是改名

color.scale() 的行為與 lighten() 不同,它是按比例縮放而不是加減固定值,結果通常更自然。轉換時要重新確認顏色,見 sass:color

載入的三件事

一、每個檔案都要自己載入。

scss
// _a.scss
@use "sass:math";   // 這裡載入了

// _b.scss
// 沒寫 → 這裡的 math.div() 會報錯

二、載入不會產生任何 CSS。 內建模組只有函式,沒有規則,載入十個也不會讓產出變大。

三、可以改命名空間。

scss
@use "sass:math" as m;

.a { width: m.div(100%, 3); }

特例:不需要載入的函式

  • if():全域可用,見 條件判斷
  • rgb()hsl()url()calc():這些是 CSS 的 函式,Sass 會原樣輸出交給瀏覽器。

calc() 裡的 Sass 變數要插值

width: calc(100% - $gap) 不會生效,要寫成 calc(100% - #{$gap}),見 插值

該把載入寫在哪

慣例是放在每個檔案最上方,緊接著自家模組之前:

scss
@use "sass:math";
@use "sass:map";
@use "../abstracts" as a;

.card {
  padding: a.space(2);
  width: math.div(100%, 3);
}

@use 必須排在所有 CSS 規則之前,規則見 @use

常見問題

為什麼舊的全域函式被棄用?

早期所有內建函式都在全域,名稱像 lightenround 這種很容易與自訂函式或未來的 CSS 函式撞名。改成模組加命名空間之後,來源一目了然,也不再有衝突。

每個檔案都要重新載入內建模組嗎?

要。模組系統沒有「全域可用」這回事,A 檔案載入了 sass:math 不代表 B 檔案也拿得到,用到的檔案都要自己在最上方寫一次。

載入內建模組會增加產出的 CSS 嗎?

不會。內建模組只提供函式,本身不含任何 CSS 規則,載入多少個都不會讓輸出變大,也不會影響編譯速度。

哪些函式不需要載入模組?

if() 是特例,它是全域可用的。另外 rgb()hsl()url() 這些是 CSS 本身的函式,會原樣輸出交給瀏覽器,不屬於 Sass 的內建模組。

延伸閱讀