新聞中心
在 CSS 中,其實(shí)存在各種各樣的函數(shù)。具體分為:

目前成都創(chuàng)新互聯(lián)公司已為數(shù)千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)絡(luò)空間、網(wǎng)站改版維護(hù)、企業(yè)網(wǎng)站設(shè)計(jì)、葉集網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
- Transform functions[1]
- Math functions[2]
- Filter functions[3]
- Color functions[4]
- Image functions[5]
- Counter functions[6]
- Font functions[7]
- Shape functions[8]
- Reference functions[9]
- CSS grid functions[10]
本文,將具體介紹其中的 CSS 數(shù)學(xué)函數(shù)(Math functions)中,已經(jīng)被瀏覽器大規(guī)模支持的 4 個(gè):
- calc()
- min()
- max()
- clamp()
為什么說(shuō)是被瀏覽器大規(guī)模支持的?因?yàn)槌诉@ 4 個(gè)目前已經(jīng)得到大規(guī)模支持的數(shù)學(xué)函數(shù)外,其實(shí)規(guī)范 CSS Values and Units Module Level 4[11] 已經(jīng)定義了諸如三角函數(shù)相關(guān) sin()、cos()、tan() 等,指數(shù)函數(shù)相關(guān) pow()、sqrt() 等等數(shù)學(xué)函數(shù),只是目前都處于實(shí)驗(yàn)室階段,還沒(méi)有瀏覽器支持它們,需要給時(shí)間一點(diǎn)時(shí)間。
Calc()
calc() 此 CSS[12] 函數(shù)允許在聲明 CSS 屬性值時(shí)執(zhí)行一些計(jì)算。
語(yǔ)法類似于:
{
width: calc(100% - 80px);
}一些需要注意的點(diǎn):
- + 和 - 運(yùn)算符的兩邊必須要有空白字符。比如,calc(50% -8px) 會(huì)被解析成為一個(gè)無(wú)效的表達(dá)式,必須寫成calc(8px + -50%)。
- * 和 / 這兩個(gè)運(yùn)算符前后不需要空白字符,但如果考慮到統(tǒng)一性,仍然推薦加上空白符。
- 用 0 作除數(shù)會(huì)使 HTML 解析器拋出異常。
- 涉及自動(dòng)布局和固定布局的表格中的表列、表列組、表行、表行組和表單元格的寬度和高度百分比的數(shù)學(xué)表達(dá)式,auto 可視為已指定。
- calc() 函數(shù)支持嵌套,但支持的方式是:把被嵌套的 calc() 函數(shù)全當(dāng)成普通的括號(hào)。(所以,函數(shù)內(nèi)直接用括號(hào)就好了。)
- calc() 支持與 CSS 變量混合使用。
看一個(gè)最常見(jiàn)的例子,頁(yè)面結(jié)構(gòu)如下:
Content
頁(yè)面的 g-footer 高為 80px,我們希望不管頁(yè)面多長(zhǎng),g-content 部分都可以占滿剩余空間,像是這樣:
這種布局使用 flex 的彈性布局可以輕松實(shí)現(xiàn),當(dāng)然,也可以使用 calc() 實(shí)現(xiàn):
.g-container {
height: 100vh;
}
.g-content {
height: calc(100vh - 80px);
}
.g-footer {
height: 80px;
}下面羅列一些 Calc() 的進(jìn)階技巧。
Calc 中的加減法與乘除法的差異
注意,calc() 中的加減法與乘除法的差異:
{
font-size: calc(1rem + 10px);
width: calc(100px + 10%);
}可以看到,加減法兩邊的操作數(shù)都是需要單位的,而乘除法,需要一個(gè)無(wú)單位數(shù),僅僅表示一個(gè)倍率:
{
width: calc(100% / 7);
animation-delay: calc(1s * 3);
}
Calc 的嵌套
calc() 函數(shù)是可以嵌套使用的,像是這樣:
{
width: calc(100vw - calc(100% - 64px));
}此時(shí),內(nèi)部的 calc() 函數(shù)可以退化寫成一個(gè)括號(hào)即可 (),所以上述代碼等價(jià)于:
{
width: calc(100vw - (100% - 64px));
}也就是嵌套內(nèi)的 calc(),calc 幾個(gè)函數(shù)字符可以省略。
Calc 內(nèi)不同單位的混合運(yùn)算
calc() 支持不同單位的混合運(yùn)算,對(duì)于長(zhǎng)度,只要是屬于長(zhǎng)度相關(guān)的單位都可以進(jìn)行混合運(yùn)算,包含這些:
- px
- %
- em
- rem
- in
- mm
- cm
- pt
- pc
- ex
- ch
- vh
- vw
- vmin
- vmax
這里有一個(gè)有意思的點(diǎn),運(yùn)算肯定是消耗性能的,早年間,有這樣一段 CSS 代碼,可以直接讓 Chrome 瀏覽器崩潰 Crash:
CSS 樣式如下:
div {
--initial-level-0: calc(1vh + 1% + 1px + 1em + 1vw + 1cm);
--level-1: calc(var(--initial-level-0) + var(--initial-level-0));
--level-2: calc(var(--level-1) + var(--level-1));
--level-3: calc(var(--level-2) + var(--level-2));
--level-4: calc(var(--level-3) + var(--level-3));
--level-5: calc(var(--level-4) + var(--level-4));
--level-6: calc(var(--level-5) + var(--level-5));
--level-7: calc(var(--level-6) + var(--level-6));
--level-8: calc(var(--level-7) + var(--level-7));
--level-9: calc(var(--level-8) + var(--level-8));
--level-10: calc(var(--level-9) + var(--level-9));
--level-11: calc(var(--level-10) + var(--level-10));
--level-12: calc(var(--level-11) + var(--level-11));
--level-13: calc(var(--level-12) + var(--level-12));
--level-14: calc(var(--level-13) + var(--level-13));
--level-15: calc(var(--level-14) + var(--level-14));
--level-16: calc(var(--level-15) + var(--level-15));
--level-17: calc(var(--level-16) + var(--level-16));
--level-18: calc(var(--level-17) + var(--level-17));
--level-19: calc(var(--level-18) + var(--level-18));
--level-20: calc(var(--level-19) + var(--level-19));
--level-21: calc(var(--level-20) + var(--level-20));
--level-22: calc(var(--level-21) + var(--level-21));
--level-23: calc(var(--level-22) + var(--level-22));
--level-24: calc(var(--level-23) + var(--level-23));
--level-25: calc(var(--level-24) + var(--level-24));
--level-26: calc(var(--level-25) + var(--level-25));
--level-27: calc(var(--level-26) + var(--level-26));
--level-28: calc(var(--level-27) + var(--level-27));
--level-29: calc(var(--level-28) + var(--level-28));
--level-30: calc(var(--level-29) + var(--level-29));
--level-final: calc(var(--level-30) + 1px);
border-width: var(--level-final);
border-style: solid;
}可以看到,從 --level-1 到 --level-30,每次的運(yùn)算量都是成倍的增長(zhǎng),最終到 --level-final 變量,展開(kāi)將有 2^30 = 1073741824 個(gè) --initial-level-0 表達(dá)式的內(nèi)容。
并且,每個(gè) --initial-level-0 表達(dá)式的內(nèi)容 -- calc(1vh + 1% + 1px + 1em + 1vw + 1cm),在瀏覽器解析的時(shí)候,也已經(jīng)足夠復(fù)雜。
混合在一起,就導(dǎo)致了瀏覽器的 BOOM(Chrome 70之前的版本),為了能看到效果,我們將上述樣式賦給某個(gè)元素被 hover 的時(shí)候,得到如下效果:
css-crash
當(dāng)然,這個(gè) BUG 目前已經(jīng)被修復(fù)了,我們也可以通過(guò)這個(gè)小 DEMO 了解到,一是 calc 是可以進(jìn)行不同單位的混合運(yùn)算的,另外一個(gè)就是注意具體使用的時(shí)候如果計(jì)算量巨大,可能會(huì)導(dǎo)致性能上較大的消耗。
當(dāng)然,不要將長(zhǎng)度單位和非長(zhǎng)度單位混合使用,像是這樣:
{
animation-delay: calc(1s + 1px);
}
Calc 搭配 CSS 自定義變量使用
calc() 函數(shù)非常重要的一個(gè)特性就是能夠搭配 CSS 自定義以及 CSS @property 變量一起使用。
最簡(jiǎn)單的一個(gè) DEMO:
:root {
--width: 10px;
}
div {
width: calc(var(--width));
}當(dāng)然,這樣看上去,根本看不出這樣的寫法的作用,好像沒(méi)有什么意義。實(shí)際應(yīng)用場(chǎng)景中,會(huì)比上述的 DEMO 要稍微復(fù)雜一些。
假設(shè)我們要實(shí)現(xiàn)這樣一個(gè) loading 動(dòng)畫效果,一開(kāi)始只有 3 個(gè)球:
可能的寫法是這樣,我們給 3 個(gè)球都添加同一個(gè)旋轉(zhuǎn)動(dòng)畫,然后分別控制他們的 animation-delay:
.item:nth-child(1) {
animation: rotate 3s infinite linear;
}
.item:nth-child(2) {
animation: rotate 3s infinite -1s linear;
}
.item:nth-child(3) {
animation: rotate 3s infinite -2s linear;
}如果有一天,這個(gè)動(dòng)畫需要擴(kuò)展成 5 個(gè)球的話,像是這樣:
我們就不得已,得去既添加 HTML,又修改 CSS。而如果借助 Calc 和 CSS 變量,這個(gè)場(chǎng)景就可以稍微簡(jiǎn)化一下。
假設(shè)只有 3 個(gè)球:
我們通過(guò) HTML 的 Style 標(biāo)簽,傳入 --delay 變量,在 CSS 中直接使用它們:
.g-item {
animation: rotate 3s infinite linear;
animation-delay: calc(var(--delay) * -1s);
}
@keyframes rotate {
to {
transform: rotate(360deg);
}
}而當(dāng)動(dòng)畫修改成 5 個(gè)球時(shí),我們就不需要修改 CSS,直接修改 HTML 即可,像是這樣:
核心的 CSS 還是這一句,不需要做任何修改:
{
animation-delay: calc(var(--delay) * -1s);
}完整的 DEMO,你可以戳這里:CodePen Demo -- Calc & CSS Variable Demo[13]
calc 搭配自定義變量時(shí)候的默認(rèn)值
還是上述的 Loading 動(dòng)畫效果,如果我的 HTML 標(biāo)簽中,有一個(gè)標(biāo)簽忘記填充 --delay 的值了,那會(huì)發(fā)生什么?
像是這樣:
{
animation-delay: calc(var(--delay) * -1s);
}由于 HTML 標(biāo)簽沒(méi)有傳入 --delay 的值,并且在 CSS 中向上查找也沒(méi)找到對(duì)應(yīng)的值,此時(shí),animation-delay: calc(var(--delay) * -1s) 這一句其實(shí)是無(wú)效的,相當(dāng)于 animation-delay: 0,效果也就是少了個(gè)球的效果:
所以,基于這種情況,可以利用 CSS 自定義變量 var() 的 fallback 機(jī)制:
{
// (--delay, 1) 中的 1 是個(gè)容錯(cuò)機(jī)制
animation-delay: calc(var(--delay, 1) * -1s);
}此時(shí),如果沒(méi)有讀取到任何 --delay 值,就會(huì)使用默認(rèn)的 1 與 -1s 進(jìn)行運(yùn)算。
Calc 字符串拼接
很多人在使用 CSS 的時(shí)候,會(huì)嘗試字符串的拼接,像是這樣:
:root {
--urlA: 'url(https://s1.ax1x.com/2022/03/07/';
--urlB: ')';
}
div {
width: 400px;
height: 400px;
background-image: calc(var(--urlA) + var(--url) + var(--urlB));
}這里想利用 calc(var(--urlA) + var(--url) + var(--urlB)) 拼出完整的在 background-image 中可使用的 URL url(https://s1.ax1x.com/2022/03/07/bsBD1I.png)。
然而,這是不被允許的(無(wú)法實(shí)現(xiàn)的)。calc 的沒(méi)有字符串拼接的能力。
唯一可能完成字符串拼接的是在元素的偽元素的 content 屬性中。但是也不是利用 calc。
來(lái)看這樣一個(gè)例子,這是錯(cuò)誤的:
:root {
--stringA: '123';
--stringB: '456';
--stringC: '789';
}
div::before {
content: calc(var(--stringA) + var(--stringB) + var(--stringC));
}此時(shí),不需要 calc,直接使用自定義變量相加即可。
因此,正確的寫法:
:root {
--stringA: '123';
--stringB: '456';
--stringC: '789';
}
div::before {
content: var(--stringA) + var(--stringB) + var(--stringC);
}此時(shí),內(nèi)容可以正常展示:
再?gòu)?qiáng)調(diào)一下,calc 的沒(méi)有字符串拼接的能力,如下的使用方式都是無(wú)法被識(shí)別的錯(cuò)誤語(yǔ)法:
.el::before {
// 不支持字符串拼接
content: calc("My " + "counter");
}
.el::before {
// 更不支持字符串乘法
content: calc("String Repeat 3 times" * 3);
}
最后
本文是現(xiàn)代 CSS 解決方案系列文章的第二篇,首發(fā)公眾號(hào),希望通過(guò)一些更易理解的語(yǔ)言、更直觀的 DEMO,講述在如今如何更好的使用 CSS 去提升我們網(wǎng)站的體驗(yàn),去提高我們的技巧。
好了,本文到此結(jié)束,希望對(duì)你有所幫助:)
參考資料
[1]Transform functions: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#transform_functions。
[2]Math functions: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#math_functions。
[3]Filter functions: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#filter_functions。
[4]Color functions: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#color_functions。
[5]Image functions: ht
當(dāng)前文章:現(xiàn)代CSS解決方案:CSS數(shù)學(xué)函數(shù)之Calc
本文鏈接:http://m.5511xx.com/article/cdooghg.html


咨詢
建站咨詢
