CSS 函式 ( 數學計算 )
CSS 雖然只是樣式語言,但也提供了一些好用的函式,讓使用者能更有彈性的設計畫面,這篇教學會介紹「數學計算」相關的 CSS 函式,例如 calc()、min()、max()、minmax()、三角函數等等,透過動態計算的方式,取得並設定動態改變的數值。
「數學計算」的 CSS 函式
下方列出「數學計算」類型的 CSS 函式 ( 支援度 All 表示主流瀏覽器都支援 ):
數學計算函式 | 說明 | 支援度 |
---|---|---|
calc() | 基本數學運算。 | All |
round() | 四捨五入。 | IE 不支援 |
clamp() | 限制數值範圍。 | IE 不支援 |
max()、min() | 最大值與最小值。 | All |
maxmin() | 最大值與最小值。 | All |
repeat() | grid 網格排版重複設定。 | All |
hypot() | 參數平方和的平方根。 | IE 不支援 |
mod()、rem() | 餘數。 | IE 不支援 |
exp()、log() | 指數函數。 | IE 不支援 |
pow()、sqrt() | 次方與平方根。 | IE 不支援 |
sin()、cos()、tan()、asin()、acos()、atan()、atan2() | 三角函數。 | IE 不支援 |
calc()
「calc()
」是「基本數學運算」CSS 函式,也是最常使用的 CSS 函式之一,通常應用在「動態計算長寬尺寸」,並支援與其他函式一起使用,基本寫法如下:
div {
width: calc(100% - 200px); /* 100% 的父元素寬度減 200px */
}
nav {
width: calc(100% / 5); /* 100% 的父元素寬度除以 5 */
}
calc()
的使用方法和限制如下:
- 僅支援「加減乘除」四則運算,混合使用時,先乘除,後加減。
- 運算符號「前後需要加上空格」,例如
calc(5px - 2px)
或calc(5px + -2px)
。- 加減需要加上「單位」,例如
calc(5px + 2px)
。- 運算需要的「單位」可以是 %、em、pt、px、vw...等 CSS 標準單位。
- 乘除的「其中一項」必須是「無單位」,例如
calc(5px * 2)
。- 0 也需要加上單位,例如
calc(5px + 0px)
。
下方的範例執行後,使用滑鼠拖拉黑色 div 方框,就可以看見內容的 nav 尺寸跟著變化,並且永遠與右側保持 20px,與下方保持 50px 距離。
<!-- HTML 程式碼 -->
<div>
<nav></nav>
</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
width:200px;
height:200px;
resize: both;
overflow: auto;
}
nav {
width: calc(100% - 20px); /* 父元素寬度的 100% 減 20px */
height: calc(100% - 50px); /* 父元素高度的 100% 減 50px */
background: red;
}
</style>
round()
「round()
」是「進位退位數學運算」CSS 函式,可以使用指定的參數和區間,將動態數值進行四捨五入、無條件捨去或進位...等數學運算,使用方法如下:
width: round(模式, 原始數值, 數值間隔);
下表列出 round()
的參數說明:
- 模式 ( 非必須 ):
- up:無條件進位。
- down:無條件捨去。
- nearest:預設值,四捨五入 ( 預設值 )。
- to-zero:四捨五入到最接近 0 的整數。
- 動態數值 ( 必須 ):具有單位的數字,不可為 0。
- 數值間隔 ( 必須 ):具有單位的數字,不可為 0。
下方的範例執行後,使用滑鼠拖拉黑色 div 方框,就可以看見內容的 nav 寬度採用 50 為區間的方式四捨五入,高度採用 20px 為區間的方式四捨五入 ( 拖拉時會有「跳動現象」,因為區間使用 50px 或 20px )。
<!-- HTML 程式碼 -->
<div>
<nav></nav>
</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
width:200px;
height:200px;
resize: both;
overflow: auto;
}
nav {
width: calc(100% - 20px); /* 父元素寬度的 100% 減 20px */
height: calc(100% - 50px); /* 父元素高度的 100% 減 50px */
background: red;
}
</style>
clamp()
「clamp()
」是「限制數值區間」CSS 函式,運用「最小值、動態數值和最大值」三個參數,鎖定數值要呈現的區間,使用方法如下:
width: clamp(最小值, 動態數值, 最大值);
clamp()
的三個參數都是必填參數,下表列出相關說明:
- 最小值:具有單位的數字,動態數值小於最小值,則以最小值呈現。
- 動態數值:具有單位的數字。
- 數值間隔:具有單位的數字,動態數值大於最大值,則以最大值呈現。
下方的範例執行後,使用滑鼠拖拉黑色 div 方框,就可以看見內容的 nav 寬度和高度最多只會到 150px,最小只會是 30px 。
<!-- HTML 程式碼 -->
<div>
<nav></nav>
</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
width:200px;
height:200px;
resize: both;
overflow: auto;
}
nav {
width: clamp(30px, 100%, 150px);
height: clamp(30px, 100%, 150px);
background: red;
}
</style>
min()、max()
「min()
」是「數字裡的最小值」CSS 函式,「max()
」表示「數字裡的最大值」,使用方法如下:
width: min(數值 A、數值 B、數值 C....); /* 取得數值 A、B、C 裡的最小值 */
width: max(數值 A、數值 B、數值 C....); /* 取得數值 A、B、C 裡的最大值 */
下方的範例執行後,使用滑鼠拖拉黑色 div 方框,就可以看見內容的 nav 寬度會從「「10% 父元素寬度、100px 和 50% 畫面高度」裡選出最大值,而 nav 高度則會從「10% 父元素高度、100px 和 50% 畫面寬度」裡選出最小值,此處的 50% 畫面高度與寬度並沒有寫相反,而是希望透過瀏覽器畫面的改變,呈現更明顯的效果。
<!-- HTML 程式碼 -->
<div>
<nav></nav>
</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
width:200px;
height:200px;
resize: both;
overflow: auto;
}
nav {
width: max(10%, 100px, 50vh);
height: min(50%, 100px, 50vw);
background: red;
}
</style>
minmax()
「minmax()
」是「大小範圍區間」CSS 函式,具有「min」和「max」兩個參數,其中一個需為「動態數值」,通常和網格排版 grid 一同使用,使用方法如下:
grid-template-columns: minmax(最小值、最大值);
下方的範例執行後,黑色 div 方框中會出現一個簡單的三格網格,使用滑鼠拖拉黑色 div 方框,網格的第一格「最小值和內容相同,最大值 100px」,第二格「最小值 200px,最大值 100%」,第三格為「150px」。
<!-- HTML 程式碼 -->
<div>
<div id="container">
<div>oxxo</div>
<div>apple</div>
<div>banana</div>
</div>
</div>
<!-- CSS 程式碼 -->
<style>
body > div {
width:300px;
height:100px;
resize: both;
overflow: auto;
border: 1px solid #000
}
#container {
display: grid;
grid-template-columns: minmax(min-content, 100px) minmax(200px, 100%) 150px;
border:1px solid red;
}
#container div {
border:1px solid red;
background:pink;
}
</style>
repeat()
「repeat()()
」是「網格的重複設定」CSS 函式,具有「重複次數」和「數值」兩個參數:
參數 | 說明 |
---|---|
重複次數 | 數字、auto-fill 或 auto-fit ,設定 auto-fill 或 auto-fit 時會在抵達重複數值最後一項後換行。 |
數值 | 類似陣列的一串數字,代表每個網格的寬度。 |
repeat()()
通常和網格排版 grid 一同使用,使用方法如下:
grid-template-columns: repeat(3, 30px 60px 90px); /* 不斷重複後方三個數值 */
grid-template-columns: repeat(auto-fill, 30px 60px 90px); /* 不斷重複後方三個數值,超過三個會換行 */
grid-template-columns: repeat(auto-fit, 30px 60px 90px); /* 不斷重複後方三個數值,超過三個會換行,用法和 auto-fill 幾乎相同 */
下方的範例執行後,畫面中會有六個粉色的 div,按照「30px、60px、90px」的寬度重複,因為有設定 auto-fill
,所以每次重複結束後就會換行。
<!-- HTML 程式碼 -->
<div id="container">
<div>a</div>
<div>b</div>
<div>c</div>
<div>a</div>
<div>b</div>
<div>c</div>
</div>
<!-- CSS 程式碼 -->
<style>
#container {
display: grid;
grid-template-columns: repeat(auto-fill, 30px 60px 90px);
grid-gap: 5px;
height: 100px;
width: 100%;
background-color: green;
padding: 10px;
}
#container > div {
background-color: pink;
padding: 5px;
}
</style>
hypot()
「hypot()
」是「參數和的平方根」CSS 函式,內容可以放入一個以上具有「單位」的數值,使用方法如下:
width: hypot(3px, 4px); /* 3x3+4x4=25,25 的平方根為 5 */
width: hypot(3px, 4px, 5px); /* 3x3+4x4+5x5=50,50 的平方根為 7.0710678118654 px */
下方的範例執行後,畫面中會出現三個 div,每個 div 的邊長等於前一個 div 的對角線長。
<!-- HTML 程式碼 -->
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid black;
margin: 10px;
float: left;
}
.a {
width: 50px;
height: 50px;
}
.b {
width: hypot(50px, 50px);
height: hypot(50px, 50px);
}
.c {
width: hypot(hypot(50px, 50px), hypot(50px, 50px));
height: hypot(hypot(50px, 50px), hypot(50px, 50px));
}
</style>
mod()、rem()
「mod()
、rem()
」是「餘數」CSS 函式,兩者用法完全相同,使用時放入「A、B」兩個具有「單位」的參數,會自動計算「A 除以 B的餘數」,餘數支援小數點,使用方法如下:
margin: rem(14.5%, 3%); /* 2.5% */
margin: rem(18px, 5px); /* 3px */
margin: rem(10rem, 6rem); /* 4rem */
margin: rem(14.5%, 3%); /* 2.5% */
margin: rem(18px, 5px); /* 3px */
margin: rem(10rem, 6rem); /* 4rem */
下方的範例執行後,畫面中會出現兩個 div,分別使用 mod()
和 rem()
函式計算和外圍間距。
<!-- HTML 程式碼 -->
<div id="box">
<div>a</div>
<div>b</div>
</div>
<!-- CSS 程式碼 -->
<style>
#box {
border: 1px solid black;
width: 200px;
height: 200px;
}
#box div {
width: 100px;
height: 50px;
background: pink;
margin: mod(100%, 15%)
}
</style>
exp()、log()
「exp()
」是「指數函數」CSS 函式,具有一個參數,參數通常使用 -1、0 或 1,使用後會回傳這個參數的指數函數數值,「log()
」表示「對數函數」,具有一個必填參數與一個選填底數 ( 預設對數底 ),使用後會根據參數計算回傳對數函數數值,因為 exp()
和 log()
計算後的數值「沒有單位」,所以只能搭配 calc() 等計算函式使用「乘法或除法」,使用方法如下:
with: calc(100px * exp(num));
with: calc(100px * log(num, 10));
下方的範例執行後,畫面中會出現兩個 div,分別使用 exp()
和 log()
函式計算寬度。
<!-- HTML 程式碼 -->
<div class="a">a</div>
<div class="b">b</div>
<!-- CSS 程式碼 -->
<style>
div {
border:1px solid #000;
height:100px;
}
.a {
width: calc(100px * exp(1)); /* 100px * 2.71828 = 270px */
}
.b {
width: calc(100px * log(5,2)); /* 100px * 2.32192 = 232px */
}
</style>
pow()、sqrt()
「pow()
」是「次方函數」CSS 函式,具有兩個參數 A 和 B,使用後會回傳 A 的 B 次方,「sqrt()
」表示「平方根函數」,具有一個參數,使用後會回傳這個參數的平方根,,因為 pow()
和 sqrt()
計算後的數值「沒有單位」,所以只能搭配 calc() 等計算函式使用「乘法或除法」,使用方法如下:
with: calc(100px * pow(A, B));
with: calc(100px * sqrt(num));
下方的範例執行後,畫面中會出現兩個 div,分別使用 pow()
和 sqrt()
函式計算寬度。
<!-- HTML 程式碼 -->
<div class="a">a</div>
<div class="b">b</div>
<!-- CSS 程式碼 -->
<style>
div {
border:1px solid #000;
height:100px;
margin:10px;
}
.a {
width: calc(20px * pow(2, 3)); /* 20 x 8 = 160px */
}
.b {
width: calc(20px * sqrt(16)); /* 20px * 4 = 80px */
}
</style>
sin()、cos()、tan()、asin()、acos()、atan()、atan2()
「sin()
、cos()
、tan()
」是「回傳數字的三角函數」CSS 函式,主要針對長度或尺寸使用,具有一個帶有「角度單位」的參數,角度單位支援「角度 deg」、「選轉方向 turn」和「徑度 rad」,使用方法如下:
with: calc(100px * sin(60deg));
with: calc(100px * cos(60deg));
with: calc(100px * tan(60deg));
,「asin()
、acos()
、atan()
」表示「回傳角度的三角函數」,主要針對旋轉的角度使用,具有一個「沒有單位」的參數,參數範圍通常是「-1~1」之間,也可使用「9999」或 「-9999」表示無窮大或無限小,使用方法如下:
transform: rotate(asin(1));
transform: rotate(acos(1));
transform: rotate(atan(1));
「atan(y, x)
」也是「回傳角度的三角函數」,具有兩個「單位類型相同」的參數 ( 例如 px 和 vx 因為最終結果都是 px,屬於同類型的單位 ),主要透過座標比例的計算求得角度,使用方法如下:
transform: rotate(atan2(3, 2));
transform: rotate(atan2(1rem, -0.5rem));
transform: rotate(atan2(20%, -30%));
transform: rotate(atan2(pi, 45));
transform: rotate(atan2(e, 30));
下方的範例執行後,畫面中會出現三個 div,分別使用不同的三角函數計算出寬度或旋轉角度。
<!-- HTML 程式碼 -->
<div class="box box-1"></div>
<div class="box box-2"></div>
<div class="box box-3"></div>
<!-- CSS 程式碼 -->
<style>
div {
border:1px solid #000;
height:50px;
width:50px;
margin:20px;
float:left;
}
.box-1 {
width: calc(100px * sin(60deg));
}
.box-2 {
transform: rotate(acos(0.5));
}
.box-3 {
transform: rotate(atan2(-1, 0.5));
}
</style>
小結
「數學計算」相關的 CSS 函式最主要都是應用在「版面動態計算」,例如在電腦版版的某些位置比較大,但在行動裝置裡比較小之類的狀況,通常一個「calc()
」函式就可以處理大部分的狀況,如果真的有其他需求,不妨也可以使用看看其他的 CSS 函式,減少一些 JavaScript 的動態計算呦。
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~