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

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


咨詢
建站咨詢
