Skip to content

Sass sass:math:除法、進位與單位處理

Sass 數學模組 sass:math 的函式

sass:math 是最常被載入的內建模組,只要專案裡有除法,就一定會用到它。

scss
@use "sass:math";

math.div:正式的除法

scss
math.div(100%, 3)     // 33.3333333333%
math.div(16px, 2)     // 8px
math.div(16px, 16px)  // 1(單位互相抵消)

斜線除法已被 棄用

scss
.a { width: $w / 2; }             // ⚠️ 警告
.b { width: math.div($w, 2); }    // ✅

原因是斜線在 CSS 裡本來就是分隔符:

css
font: 12px/1.5 sans-serif;
grid-area: 1 / 2 / 3 / 4;

Sass 無法可靠分辨你要哪一種,所以用函式明確表達。

單位會抵消

scss
math.div(16px, 16px)   // 1,不帶單位
math.div(16px, 2)      // 8px
math.div(2, 16px)      // 0.125/px ← 很少是你想要的

想保留單位就讓 除數不帶單位。相同單位相除得到純比例,這通常正是換算 rem 時要的:

scss
@function rem($px, $base: 16px) {
  @return math.div($px, $base) * 1rem;
}

進位與取整

scss
math.round(4.6)    // 5,四捨五入
math.ceil(4.1)     // 5,無條件進位
math.floor(4.9)    // 4,無條件捨去
math.abs(-4px)     // 4px

柵格寬度取到小數點後幾位時很實用:

scss
@function round-to($n, $digits: 2) {
  $factor: math.pow(10, $digits);
  @return math.div(math.round($n * $factor), $factor);
}

.col { width: round-to(math.percentage(math.div(1, 3)), 4); } // 33.3333%

percentage:轉百分比

scss
math.percentage(math.div(1, 3))   // 33.3333333333%
math.percentage(0.5)              // 50%

輸入必須不帶單位

math.percentage(16px) 會報錯。先用 math.div() 算出無單位的比例再轉。

比大小

scss
math.min(10px, 20px, 5px)   // 5px
math.max(10px, 20px)        // 20px
math.clamp(8px, 20px, 16px) // 16px,夾在上下限之間

math.clamp 不是 CSS 的 clamp()

math.clamp() 在編譯期算出一個固定值;CSS 的 clamp() 留在樣式裡由瀏覽器依實際視窗計算。做流體字級要用後者:

scss
.hero { font-size: clamp(1.5rem, 5vw, 3rem); }

單位的檢查與處理

scss
math.is-unitless(16)      // true
math.is-unitless(16px)    // false
math.unit(16px)           // "px"
math.compatible(16px, 2em) // false,不可換算

寫工具函式時用它擋掉錯誤輸入:

scss
@function rem($px, $base: 16px) {
  @if math.is-unitless($px) {
    $px: $px * 1px;   // 允許只寫數字
  }
  @return math.div($px, $base) * 1rem;
}

次方、平方根與常數

scss
math.pow(2, 10)     // 1024
math.sqrt(16)       // 4
math.hypot(3, 4)    // 5
$pi: math.$pi;      // 3.1415926536
$e:  math.$e;

模組化的字級刻度常用到次方:

scss
$ratio: 1.25;

@for $i from 1 through 5 {
  .h#{$i} { font-size: math.pow($ratio, 6 - $i) * 1rem; }
}

三角函式

scss
math.sin(math.$pi * 0.5)   // 1
math.cos(0)                // 1
math.atan2(1, 1)           // 45deg

環狀排列的元素、扇形選單這類版面會用到。

與 CSS calc() 的分工

sass:mathcalc()
何時算編譯期瀏覽器執行時
混用 px 與 %不行可以
吃得到 自訂屬性不行可以
scss
.main {
  padding: math.div($gap, 2);              // 編譯期
  width: calc(100% - #{$gap * 2});         // 執行期
}

規則見 運算子

常見問題

為什麼除法要用 math.div 而不是斜線?

因為斜線在 CSS 裡是分隔符,出現在 font 簡寫與 grid-area 這些地方,Sass 無法判斷你要的是除法還是分隔。改用函式就沒有歧義,斜線除法已被正式棄用。

除法之後單位跑掉了怎麼辦?

兩個相同單位的數相除會互相抵消,得到不帶單位的數字,這通常正是你要的比例。想保留單位就讓除數不帶單位,例如把長度除以純數字。

怎麼把小數轉成百分比?

math.percentage(),它把不帶單位的數字乘以一百並加上百分號。注意輸入必須是無單位的,先用 math.div() 算出比例再轉換。

math.clamp 和 CSS 的 clamp() 一樣嗎?

不一樣。math.clamp() 在編譯期就算出一個固定值,CSS 的 clamp() 則留在樣式裡由瀏覽器依實際視窗計算。要做流體字級請用 CSS 的那個。

延伸閱讀