数学计算
CSS 虽然只是样式语言,但也提供了一些好用的函数,让用户能更有弹性的设计划面,这篇教学会介绍“数学计算”相关的 CSS 函数,例如 calc()、min()、max()、minmax()、三角函数等等,透过动态计算的方式,取得并设定动态改变的数值。
教学影片
搭配教学影片一起阅读,效果会更好!欢迎大家订阅 STEAM 教育学习网的 Youtube 频道。
“数学计算”的 CSS 函数
下方列出“数学计算”类型的 CSS 函数 ( 目前主流浏览器都支援 ):
| 数学计算函数 | 说明 |
|---|---|
| calc() | 基本数学运算。 |
| round() | 四舍五入。 |
| clamp() | 限制数值范围。 |
| max()、min() | 最大值与最小值。 |
| hypot() | 参数平方和。 |
| mod()、rem() | 余数。 |
| exp()、log() | 指数与对数。 |
| pow()、sqrt() | 次方与平方根。 |
| sin()、cos()、tan()、asin()、acos()、atan()、atan2() | 三角函数。 |
| maxmin() | grid 网格排版最大值与最小值。 |
| repeat() | grid 网格排版重复设定。 |
calc()
“calc()”是“基本数学运算”CSS 函数 ( calculation ),也是最常使用的 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: round(100%, 20px); /* 父元素寬度的 100%,但四捨五到最接近 20px 倍數的整數 */
height: round(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>
hypot()
“hypot()”是“参数的平方和加总的平方根”CSS 函数,这个函数本质是求直角三角形的斜边长 ( hypotenuse )
,内容可以放入一个以上具有“单位”的数值,使用方法如下:
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 函数 ( modulus、remainder ),两者用法完全相同,使用时放入“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 函数 ( power ),具有两个参数 A 和 B,使用后会回传 A 的 B 次方,“sqrt()”表示“平方根函数”( square root ),具有一个参数,使用后会回传这个参数的平方根,因为 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));
“atan2(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>
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>
小结
“数学计算”相关的 CSS 函数最主要都是应用在“版面动态计算”,例如在电脑版版的某些位置比较大,但在移动设备里比较小之类的状况,通常一个“calc()”函数就可以处理大部分的状况,如果真的有其他需求,不妨也可以使用看看其他的 CSS 函数,减少一些 JavaScript 的动态计算呦。
微信扫码关注
抖音扫码关注