Sass 自訂函式 @function:回傳值而不是樣式
混入 產生 樣式,函式產生 值。一句話劃清界線:
想把結果放進屬性值的位置 → 函式。想產生一整段宣告 → 混入。
定義與呼叫
@use "sass:math";
@function rem($px, $base: 16px) {
@return math.div($px, $base) * 1rem;
}
.title {
font-size: rem(24px); // 1.5rem
padding: rem(8px) rem(16px);
}@return 把值交出去,函式就結束了。呼叫時就像用內建函式一樣。
函式裡不能寫 CSS
@function bad($x) {
color: red; // ❌ Error
@return $x;
}函式的內容只能是:變數指派、@if、迴圈、@debug / @warn / @error、以及 @return。
多個 @return
搭配條件判斷,不同情況回傳不同的值:
@use "sass:math";
@use "sass:color";
// 依背景色決定文字要用深色還是淺色
@function contrast-text($bg) {
@if color.channel($bg, "lightness", $space: hsl) > 60% {
@return #1a1a1a;
} @else {
@return #ffffff;
}
}
.badge {
background: #ffd43b;
color: contrast-text(#ffd43b); // #1a1a1a
}執行到第一個 @return 就結束。每一條路徑都必須有 @return,漏掉某個分支會編譯錯誤。
幾個實用的函式
@use "sass:math";
@use "sass:map";
@use "sass:meta";
// px 轉 rem
@function rem($px, $base: 16px) {
@return math.div($px, $base) * 1rem;
}
// 從主題 map 取色,取不到就明確報錯
@function color-of($name) {
@if not map.has-key($theme, $name) {
@error "色彩 #{$name} 不存在,可用的有:#{map.keys($theme)}。";
}
@return map.get($theme, $name);
}
// 間距刻度:8px 的倍數
@function space($n) {
@return $n * 8px;
}.card {
padding: space(2); // 16px
color: color-of(primary);
font-size: rem(18px);
}這種取值函式比直接用 map.get() 好
color-of(primary) 打錯字時會得到一句清楚的錯誤訊息與可用清單;map.get($theme, primry) 只會安靜回傳 null,然後那一行宣告就消失了。錯誤訊息的寫法見 除錯。
參數的規則與混入相同
預設值、關鍵字引數、任意參數的寫法完全一樣:
@function clamp-size($min, $preferred, $max: 64px) {
@return clamp(#{$min}, #{$preferred}, #{$max});
}
.hero {
font-size: clamp-size($min: 24px, $preferred: 5vw);
}細節見 混入的參數。
命名要加前綴
自訂函式與 內建函式、未來的 CSS 函式都可能撞名:
@function rem($px) { } // ⚠️ 太通用
@function app-rem($px) { } // ✅ 加專案前綴用 @use 載入時本來就有命名空間(fn.rem()),衝突風險小很多;但若習慣用 as * 省略前綴,就更該自己加。
純函式:同樣的輸入永遠同樣的輸出
函式應該只依賴它的參數,不要去讀寫全域狀態:
// ❌ 依賴外部變數,換個檔案結果就不一樣
$base: 16px;
@function bad-rem($px) {
@return math.div($px, $base) * 1rem;
}
// ✅ 基準值也當參數,有預設值
@function rem($px, $base: 16px) {
@return math.div($px, $base) * 1rem;
}尤其不要在函式裡用 !global 改變數,理由見 變數旗標。
常見問題
函式和混入該怎麼選?
看你要的是值還是樣式。需要一個可以放進屬性值位置的結果就寫函式,需要產生一整段宣告就寫混入。函式裡不能寫 CSS 規則,混入也不能回傳值。
函式可以寫 CSS 宣告嗎?
不行。函式的內容只能是變數指派、條件判斷、迴圈與 @return,寫進 CSS 宣告會直接編譯錯誤。函式的唯一產物就是它回傳的那個值。
自訂函式的名稱會和內建函式衝突嗎?
有可能,也可能與未來的 CSS 函式撞名。建議幫自訂函式加上專案前綴,例如寫成 app-rem() 而不是 rem(),模組系統的命名空間也能避免大部分衝突。
函式裡可以有多個 @return 嗎?
可以,搭配 @if 在不同分支各自回傳即可。執行到第一個 @return 就結束,後面的程式碼不會再跑。但每一條路徑都必須有 @return,否則會出現錯誤。