CSS動態(tài)計算,calc()使用指南(下篇)
從之前的文章:CSS 計算屬性 calc()的完整指南(一),我們可以學習到幾個方面:
calc() 只作用于屬性值
calc() 用于長度和其他數(shù)值
不能在媒體查詢中使用
混合單位
與預處理器數(shù)學比較
本文接著之前未完的工作,恰好是周末,一次把它完成。如果我的工作對你有幫助,希望可以點個贊和收藏分享。
顯示數(shù)學
即使你沒有使用只有calc()才能實現(xiàn)的功能,也可以用它在CSS里面 "展示你的工作"。例如,假設你需要精確計算一個元素的1?7的寬度......。
.el {/* This is easier to understand */width: calc(100% / 7);/* Than this is */width: 14.2857142857%;}
這可能會在某種自創(chuàng)的CSS?API中泛起,好比。
[data-columns="7"] .col { width: calc(100% / 7); }[data-columns="6"] .col { width: calc(100% / 6); }[data-columns="5"] .col { width: calc(100% / 5); }[data-columns="4"] .col { width: calc(100% / 4); }[data-columns="3"] .col { width: calc(100% / 3); }[data-columns="2"] .col { width: calc(100% / 2); }
calc()的數(shù)學運算符
你已經(jīng)有了+、-、*和/,但它們在使用方法上有所不同。
加法(+)和減法(-)要求這兩個數(shù)都是長度
.el {/* 有效?? */margin: calc(10px + 10px);/* 無效的?? */margin: calc(10px + 5);}
無效的值會使整個單項聲明無效。
除法(/)要求第二個數(shù)字是無單位的。
.el {/* 有效的?? */margin: calc(30px / 3);/* 無效的?? */margin: calc(30px / 10px);/* 無效的?? (不能除以0) */margin: calc(30px / 0);}
乘法(*)要求其中一個數(shù)是無單位的。
.el {/* 有效的 ?? */margin: calc(10px * 3);/* 有效的 ?? */margin: calc(3 * 10px);/* 無效的 ?? */margin: calc(30px * 3px);}
空白空間很重要
嗯,對于加法和減法來說是這樣的。
.el {/* 有效的 ?? */font-size: calc(3vw + 2px);/* 無效的 ?? */font-size: calc(3vw+2px);/* 有效的 ?? */font-size: calc(3vw - 2px);/* 無效的 ?? */font-size: calc(3vw-2px);}
負數(shù)是可以的(例如 calc(5vw - -5px) ),但這是一個例子,說明空格不僅是必需的,而且是有用的。
Tab Atkins告訴我,+和-周圍需要間隔的原因其實是出于解析的考慮。我不能說我完全理解,但例如,2px-3px被解析為數(shù)字 "2 "和單位 "px-3px",這對任何人都沒有好處,而+還有其他問題,比如被 "數(shù)字語法消耗"。我本來猜測空格應該是和自定義屬性的--語法有關,但沒有!
乘法和除法不需要運算符周圍的空格。但我認為好的一般建議是,為了其他運算符的可讀性和肌肉記憶,應該包括這些空格。
外圍的空白并不重要。如果你愿意,你甚至可以做換行符。
.el {/* 有效的 ?? */width: calc(100% / 3);}
不過,請注意以下事項:calc() 與開頭括號之間沒有空格。
.el {/* 無效的 ?? */width: calc (100% / 3);}
嵌套計算(calc())
你可以這樣做,但沒有必要。這和使用一組額外的小括號而不使用 calc()部分是一樣的。例如
.el {width: calc(calc(100% / 3)-calc(1rem * 2));}
您不需要在calc() 內部使用這些代碼,因為括號可以單獨工作:
.el {width: calc((100% / 3)-(1rem * 2));}
而在這種情況下,即使沒有括號,"運算順序 "也能幫助我們。也就是說,除法和乘法是先發(fā)生的(在加法和減法之前),所以根本不需要括號??梢赃@樣寫:
.el {width: calc(100% / 3 - 1rem * 2);}
但是,如果您想增加清晰度,請隨意使用。如果操作順序不利于您(例如,您確實確實需要先進行加法或減法),則需要括號。
.el {/* This */width: calc(100% + 2rem / 2);/* Is very different from this */width: calc((100% + 2rem) / 2);}
CSS自定義屬性和calc() ??
除了calc()能夠混合單位的驚人能力之外,calc()的下一個最棒的地方就是與自定義屬性一起使用。自定義屬性可以有一些你在計算中使用的值。
html {--spacing: 10px;}.module {padding: calc(var(--spacing) * 2);}
我相信你可以想象一個CSS設置,通過設置一堆CSS自定義屬性,然后讓CSS的其他部分根據(jù)需要使用它們,大量的配置發(fā)生在頂部。
自定義屬性也可以相互引用。這里有一個例子,其中使用了一些數(shù)學(注意一開始沒有calc()函數(shù)),然后再應用。(最終還是要放在calc()里面。)
html {--spacing: 10px;--spacing-L: var(--spacing) * 2;--spacing-XL: var(--spacing) * 3;}.module[data-spacing="XL"] {padding: calc(var(--spacing-XL));}
你可能不喜歡這樣,因為你需要記住你使用屬性的地方的calc(),但從可讀性的角度來看,這是可能的,而且可能很有趣。
自定義屬性可以來自HTML,這有時是一件很酷很有用的事情。(參見Splitting.js如何為單詞/字符添加索引的例子。)
<div style="--index: 1;"> ... div><div style="--index: 2;"> ... div><div style="--index: 3;"> ... div>
div {/* Index value comes from the HTML (with a fallback) */animation-delay: calc(var(--index, 1) * 0.2s);}
以后增加單位
如果你在存儲數(shù)字時沒有單位,或者提前用沒有單位的數(shù)字做數(shù)學運算,你總是可以等到應用數(shù)字時,通過乘以1和單位來加單位。
html {--importantNumber: 2;}.el {/* Number stays 2, but it has a unit now */padding: calc(var(--importantNumber) * 1rem);}
弄亂顏色
像RGB和HSL這樣的顏色格式有數(shù)字,你可以用calc()來搞。例如,設置一些基本的HSL值,然后改變它們形成一個你自己創(chuàng)造的系統(tǒng)(例子)。
html {--H: 100;--S: 100%;--L: 50%;}.el {background: hsl(calc(var(--H) + 20),calc(var(--S) - 10%),calc(var(--L) + 30%))}
你不能把calc()和attr()結合在一起
CSS中的attr()函數(shù)看起來很吸引人,就像你可以從HTML中提取屬性值并使用它們。但是...
<div data-color="red">...div>div {/* Nope */color: attr(data-color);}
不幸的是,這里沒有 "類型 "在起作用,所以attr()的唯一作用是與內容屬性結合的字符串。這意味著這個可以用:
div::before {content: attr(data-color);}
我提到這一點,是因為可能很想用這種方式拉出一個數(shù)字來用于計算,比如:
class="grid" data-columns="7" data-gap="2">...</div>
.grid { display: grid;
/* Neither of these work */ grid-template-columns: repeat(attr(data-columns), 1fr); grid-gap: calc(1rem * attr(data-gap));}
幸運的是,這并不重要,因為在HTML中的自定義屬性同樣有用,甚至更有用!
class="grid" style="--columns: 7; --gap: 2rem;">...</div>
.grid { display: grid;
/* Yep! */ grid-template-columns: repeat(var(--columns), 1fr); grid-gap: calc(var(--gap));}
瀏覽器工具
瀏覽器DevTools將向您展示您在樣式表中編寫的calc()。
Firefox DevTools – Rules
如果您需要找出計算值,有一個計算選項卡(在所有瀏覽器的DevTools中,至少在我所知道的范圍內)會向您顯示它。
Chrome DevTools – Computed
瀏覽器支持
這個瀏覽器支持數(shù)據(jù)來自Caniuse,它有更詳細的數(shù)據(jù)。數(shù)字表示瀏覽器支持該版本及以上的功能。

如果你真的需要支持超遠期(如IE 8或Firefox 3.6),通常的技巧是在使用calc()的屬性或值之前再添加一個屬性或值。
.el { width: 92%; /* Fallback */ width: calc(100% - 2rem);}
calc()也有不少已知的問題,但都是針對舊瀏覽器的。canIuse......列出了13個,下面是一小部分。
Firefox <59 不支持color函數(shù)的calc()。例如:color: hsl(calc(60 * 2), 100%, 50%)
當calc()用于任何一個值時,IE 9 - 11將不會渲染盒影屬性。
IE 9 - 11和Edge都不支持表格單元格上的width: calc()。
用例方
我問了一些CSS開發(fā)者最后一次使用calc()是什么時候,這樣我們就可以在這里品味一下其他人在日常工作中是如何使用它的。
我用它創(chuàng)建了一個.full-bleed 實用工具類:.full-bleed{width:100vw;margin left:calc(50%-50vw);}我想calc()在我的前3個CSS中。
我用它來為粘性頁腳騰出空間。
我用它來設置一些流體字體/動態(tài)排版......根據(jù)最小值、最大值和視口單位的變化率來計算字體大小。不僅僅是字體大小,還有行高。
如果你使用calc()作為流體字體情況的一部分,涉及到視口單位等,確保你包含一個使用rem或em的單位,這樣用戶仍然有一些控制權,通過放大或縮小他們需要的字體。
我很喜歡的一個方法是有一個 "內容寬度 "的自定義屬性,然后用它來創(chuàng)建我需要的間距,比如 margins: .margin { width: calc( (100vw - var(--content-width)) / 2); }
我用它創(chuàng)建了一個跨瀏覽器的drop-cap組件。下面是它的一部分。.drop-cap { --drop-cap-lines: 3; font-size: calc(1em * var(-drop-cap-lines) * var(-body-line-height)); }。
我用它來使文章頁面上的一些圖片溢出其容器。
我用它與padding和vw/vh單位相結合,在頁面上正確地放置了一個可視化。
我用它來克服背景-位置的限制,但特別是在漸變中定位顏色停止的限制。比如 "在底部少停0.75em"。
其他技巧
一個兩層網(wǎng)格,可以分成一列,而無需媒體查詢
一個縱橫比的頭部組件
增強高對比度的顏色
幫助解決基于百分比的剪輯路徑的坐標問題
以上就是這篇文章的全部內容了,讀下來收獲很大,沒想到calc()屬性還有這么多限制和作用的。
結語
「關注公眾號IQ前端,一個專注于CSS/JS開發(fā)技巧的前端公眾號,更多前端小干貨等著你喔」
