為什麼CSS中的calc函數可能會不生效?
前言
在早期如果想要對某一些樣式進行動態計算,絕大多數的做法都是使用JavaScript來進行,當時的CSS在面對這種場景顯得有點無能為力。但是,當CSS3中新增了calc
函數時,面對這種場景,JavaScript不再是我們的第一選擇,我們只用 CSS 就可以進行相當複雜的計算了。在使用calc
的過程中,相信大家或多或少都遇到過下面這些「坑」。
如果這篇文章有幫助到你,❤️關注+點贊❤️鼓勵一下作者,文章公眾號首發,關注 前端南玖
第一時間獲取最新文章~
常見的「坑」
先來介紹css使用calc
無效的兩種常見情況:
運算符之間沒加空格
/*錯誤寫法*/
div{
width: calc(100%-50px);
}
/*正確寫法*/
div{
width: calc(100% - 50px);
}
這裡錯誤寫法中-
兩邊沒加空格,導致width不生效。但並不是所有運算符間都需要加空格,只有 +
和 -
需要加空格,因為運算允許負數的出現,如:
div{
width: calc(100% + -50px);
}
所以,為了統一,建議所有運算符都加上空格,防止記憶混淆。
運算值沒帶單位
我們都知道在寫css時,如果數值為0我們一般會省略它的單位,比如:0px
我們一般會直接寫成0
。但是在calc()
函數中如果0不帶單位,也會導致不生效。
/*錯誤寫法*/
div{
width: calc(0 + 100px);
}
/*正確寫法*/
div{
width: calc(0px + 100px);
}
這裡上面的不帶單位的寫法也是不生效的。這裡我相信很多人都會有疑問,為什麼0還需要帶個單位?
這是因為calc()
函數傳入的是一個數學表達式,而表達式的值可以有多種類型,如長度、百分比、角度等。那如果你傳個 0 進去,沒單位的話,怎麼知道這個 0 是屬於什麼類型?
低版本less處理calc衝突
以下程式碼在低版本less中會被編譯成你意想不到的結果:
.box {
width: calc(100% - 50px)
}
編譯後:
.box {
width: calc(50%)
}
導致這個結果的原因在於less中有一套自己的運算規則:
less運算(Operations)
算術運算符 +
、-
、*
、/
可以對任何數字、顏色或變數進行運算。如果可能的話,算術運算符在加、減或比較之前會進行單位換算。計算的結果以最左側操作數的單位類型為準。如果單位換算無效或失去意義,則忽略單位。無效的單位換算例如:px 到 cm 或 rad 到 % 的轉換。
// 所有操作數被轉換成相同的單位
@conversion-1: 5cm + 10mm; // 結果是 6cm
@conversion-2: 2 - 3cm - 5mm; // 結果是 -1.5cm
// conversion is impossible
@incompatible-units: 2 + 5px - 3cm; // 結果是 4px
// example with variables
@base: 5%;
@filler: @base * 2; // 結果是 10%
@other: @base + @filler; // 結果是 15%
乘法和除法不作轉換。因為這兩種運算在大多數情況下都沒有意義,一個長度乘以一個長度就得到一個區域,而 CSS 是不支援指定區域的。Less 將按數字的原樣進行操作,並將為計算結果指定明確的單位類型。
所以上面的less會被進行如下處理:
- 由於100%與50px單位不同,會被轉換成相同的單位%(以最左側操作數的單位類型為準)
- 再進行減法運算得到50%
解決方案
- 轉義
轉義(Escaping)允許你使用任意字元串作為屬性或變數值。任何
~"anything"
或~'anything'
形式的內容都將按原樣輸出,除非 interpolation。
我們希望less不要幫我們處理,所以這裡我們可以使用less的轉義語法讓calc
函數原樣輸出就好了
.box {
width: calc(~"100% - 50px")
}
- 升級
less
和less-loader
了解calc函數
CSS calc 函數用於在指定 CSS 屬性值時執行計算。它可以用於可以使用任何數值的地方。它將表達式作為參數,並將結果用作使用它的 CSS 屬性的值。我們可以用它進行加法
+
、減法-
、乘法*
和除法/
。
語法
/* property: calc(expression) */
width: calc(100% - 80px);
calc() 函數用一個表達式作為它的參數,用這個表達式的結果作為值。這個表達式可以是任何如下操作符的組合,採用標準操作符處理法則的簡單表達式。
+
加法-
減法*
乘法,乘數中至少有一個是 number/
除法,除數必須是number
規則
+
和-
運算符的兩邊必須要有空白字元。 比如,calc(50% -8px)
會被解析成為一個無效的表達式,解析結果是:一個百分比 後跟一個負數長度值。而加有空白字元的、有效的表達式calc(8px + -50%)
會被解析成為:一個長度 後跟一個加號 再跟一個負百分比。*
和/
這兩個運算符前後不需要空白字元,但如果考慮到統一性,仍然推薦加上空白符。- 用 0 作除數會使 HTML 解析器拋出異常。
- 涉及自動布局和固定布局的表格中的表列、表列組、錶行、錶行組和表單元格的寬度和高度百分比的數學表達式,
auto
可視為已指定。 calc()
函數支援嵌套,但支援的方式是:把被嵌套的calc()
函數全當成普通的括弧。
解惑
想要了解前面那些坑產生的原因,我們得先了解CSS中的基礎語法與數據類型:
DIMENSION語法
DIMENSION {num}{ident}
這裡的num
值的是數字,那麼ident
代表什麼呢,這個我們也可以在CSS規範中找到答案
ident
ident [-]?{nmstart}{nmchar}*
nmstart和nmchar
nmstart [_a-z]|{nonascii}|{escape}
nmchar [_a-z0-9-]|{nonascii}|{escape}
解惑calc(100%-50px)
了解完CSS的基礎語法與數據結構,我們現在可以來看看解析器是如何解析calc(100%-50px)
的。
- 首先DIMENSION語法,{num}{ident}會將其分割為
num:100
、ident:%和-100px
%
是單位,這個應該沒有疑問-100px
這個符合nmchar語法,所以沒有將其拆開,而是保留作為單位解析,但CSS中沒有-100px
這個單位,所以這個表達式不會生效
兼容性
calc 函數具有驚人的瀏覽器支援,一直到 IE9。如果你用舊版瀏覽器或 Opera Mini 編寫程式碼,請考慮使用數值作為後備。
最後
喜歡的同學歡迎點個贊呀,想要查看源碼的同學快來公眾號回復碎片吧~
我是南玖,我們下期見!!!