前言
在早期如果想要對某一些樣式進行動态計算,絕大多數的做法都是使用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"
形式的内容都将按原樣輸出,除非 interpolation。
~'anything'
我們希望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
-
是機關,這個應該沒有疑問%
-
這個符合nmchar文法,是以沒有将其拆開,而是保留作為機關解析,但CSS中沒有-100px
這個機關,是以這個表達式不會生效-100px
相容性
calc 函數具有驚人的浏覽器支援,一直到 IE9。如果你用舊版浏覽器或 Opera Mini 編寫代碼,請考慮使用數值作為後備。