使用 CSS 自定義屬性使您的 CSS 動態化

已發表: 2022-03-11

如果您已經編寫 CSS 有一段時間了,那麼您一定在某個時間點感到需要變量。 CSS 自定義屬性有點像 CSS 自己的變量實現。 但是,如果使用得當,它們可以不僅僅是變量。

CSS 自定義屬性允許您:

  • 為具有您選擇的名稱的屬性分配任意值
  • 使用var()函數在其他屬性中使用這些值

儘管目前對 CSS 自定義屬性的支持有點困難,並且一些瀏覽器在需要預先激活或設置為 true 的標誌下支持它們,但預計它們的支持會在未來急劇增加,因此了解這一點很重要如何使用和利用它們。 1

使用 CSS 自定義屬性

在本文中,您將了解如何使用 CSS 自定義屬性使您的樣式表更具動態性,也許會使資產管道中的額外 Sass/LESS 步驟過時。

原始且功能較弱的 CSS 變量

在開始討論 CSS 自定義屬性之前,需要注意的是,很長一段時間以來,CSS 都有一個變量,那就是currentColor關鍵字。 這個很少使用但被廣泛支持的變量,指的是元素的當前顏色值。 它可以用於任何接受color值的聲明,並且可以完美地級聯。

我們來看一個例子:

 .element { color: blue; border: 2px solid currentColor; /* Sets a solid, 2px wide, blue border to the element */ }

除了級聯之外,這還可以產生以下內容:

 .element span { background: currentColor; /* Sets a blue background color for every span child of .element, unless a color property is declared in this same block */ } .element span.red { color: red; /* Sets a red background color for every span child of .element that has the class .red, since currentColor is applied to the background of every span child of .element no matter if they have the .red class or not */ }

currentColor的主要問題,除了它本身沒有在規範中作為變量之外,它只接受 color 屬性的值,這在某些情況下可能難以使用。

成熟的 CSS 變量

使用 CSS 預處理器/後處理器的主要優點之一是它們允許將值存儲在關鍵字中,並在必要時將它們限定為某個選擇器。

在開發人員長期要求之後,編寫了一份解釋 CSS 原生變量的草案。 這些正式稱為 CSS 自定義屬性,但有時也稱為 CSS 變量。

本機 CSS 自定義屬性的當前規範涵蓋了與前/後處理器變量相同的所有行為。 這使您能夠存儲顏色代碼、具有所有已知單位的尺寸,或者在需要時僅存儲整數(例如,當您需要使用相同的除數或乘數時)。

CSS 自定義屬性的語法與其他語言相比有點奇怪,但如果將它們的語法與同一個 CSS 生態系統中的其他功能進行比較,它就會很有意義:

 :root { --color-black: #2e2e2e; } .element { background: var(--color-black); }

現在,您可能會想:“那是什麼語法!?”

好吧,Lea Verou 以絕對簡單的方式解釋了這種“破折號”語法的原因,正如她在她精彩的演講 CSS 變量:var(–subtitle) 中所說:

它們的工作方式與任何其他 CSS 屬性 [...] 完全相同。 很多人問我為什麼我們不使用美元 [符號] 或類似的東西,我們不使用美元 [符號] 的原因是我們希望人們能夠同時使用 SASS 或預處理器變量和CSS 變量。 它們都是不同的東西,它們實現不同的目標,有些事情你可以用 CSS 變量做而你絕對不能用 SASS,有些事情你可以用 SASS 變量做你不能用 CSS 變量做,所以我們想要人們能夠在同一個樣式表中同時使用它們,因此您可以將破折號語法想像成帶有空前綴的前綴屬性。

我們可以使用var()函數檢索自定義屬性的值,除了選擇器、屬性名稱或媒體查詢聲明之外,我們可以在任何地方使用它。

值得注意的是,雖然前/後處理器變量僅在編譯時使用,但 CSS 變量可以動態使用和更新。 這是什麼意思? 這意味著它們被保留在實際的 CSS 樣式表中。 因此,即使在樣式表被編譯後,它們是變量的概念仍然存在。

為了更清楚,讓我用一些例子來說明情況。 以下代碼塊是 SASS 樣式表的一部分:

 :root { $value: 30px; } @media screen and (min-width: 768px) { $value: 60px; } .corners { border-radius: $value; }

這個 SASS 聲明和規則片段編譯成 CSS 如下:

 .corners { border-radius: 30px; }

您可以看到:rootmedia查詢中的屬性在編譯後都丟失了,因為 SASS 變量不能存在於 CSS 文件中(或者,更準確地說,它們可以強制存在於 CSS 文件中,但被忽略因為它們的一些語法是無效的 CSS),所以變量的值不能在之後更新。

現在讓我們考慮相同的情況,但僅使用 CSS 變量而不應用 CSS 預處理器/後處理器(即,不執行任何編譯或編譯):

 :root { --value: 30px; } @media screen and (min-width: 768px) { --value: 60px; } .corners { border-radius: var(--value); }

顯然,沒有任何變化,因為我們沒有編譯/轉譯任何東西,並且自定義屬性的值可以動態更新。 因此,例如,如果我們使用 JavaScript 之類的東西更改--value的值,則該值將在使用 var() 函數調用它的每個實例中更新。

自定義屬性的功能使此功能如此強大,您甚至可以執行自動前綴等操作。

Lea Verou 使用clip-path屬性設置了一個示例。 我們首先將要添加前綴的屬性的值設置為initial但使用自定義屬性,然後繼續將每個前綴屬性的值設置為自定義屬性值:

 * { --clip-path: initial; -webkit-clip-path: var(--clip-path); clip-path: var(--clip-path); }

在此之後,剩下的就是更改選擇器中自定義屬性的值:

 header { --clip-path: polygon(0% 0%, 100% 0%, 100% calc(100% - 2.5em), 0% 100%); }

如果您想對此了解更多,請查看 Lea 關於使用 CSS 變量進行自動前綴的完整文章。

防彈 CSS 自定義屬性

如前所述,瀏覽器對 CSS 自定義屬性的支持在很大程度上仍然是非標準的。 那麼如何克服呢?

這就是 PostCSS 及其插件 postcss-css-variables 發揮作用的地方。

如果您想知道 PostCSS 是什麼,請查看我的文章 PostCSS:SASS 的新播放日期,並在完成後返回此內容。 然後,您將對使用這個神奇的工具可以做什麼有一個基本的了解,並且在閱讀本文的其餘部分時不會感到迷失方向。

使用postcss-css-variables插件,並將其preserve選項設置為 true,我們可以將所有var()函數聲明保留在輸出中,並將計算值作為後備聲明。 它還保留計算的--var聲明。 請記住,使用這個 PostCSS 插件,自定義屬性可以在轉譯過程後動態更新,但回退值將保持不變,除非它們是專門針對並單獨顯式更改的。

如果您正在尋找一種無需預處理器/後處理器的方式來使用 CSS 變量,您始終可以使用 CSS @support規則手動檢查當前支持,並在支持不完整或不存在時應用適當的回退。 例如:

 :root { --color-blue: #1e90ff; /* hex value for dodgerblue color */ } .element { background: var(--color-blue); } @supports (not(--value: 0)) { /* CSS variables not supported */ .element { background: dodgerblue; } }

使用 JavaScript 更改自定義屬性的值

在整篇文章中,我一直在提到可以使用 JavaScript 更新變量,所以讓我們開始吧。

假設你有一個淺色主題並想將其切換為深色主題,假設你有一些如下所示的 CSS:

 :root { --text-color: black; --background-color: white; } body { color: var(--text-color); background: var(--background-color); }

您可以通過執行以下操作來更新--text-color--background-color自定義屬性:

 var bodyStyles = document.body.style; bodyStyles.setProperty('--text-color', 'white'); bodyStyles.setProperty('--background-color', 'black');

有趣的用例

經過多年關於 CSS 自定義屬性規範的開發和討論,出現了一些有趣的用例。 這裡有一些例子:

主題:在實現 CSS 變量時,為網站使用一組主題相當容易。 想要您當前風格的淺色或深色變化嗎? 只需使用 JavaScript 更改一些自定義屬性的值即可。

間距調整:需要微調站點的間距,比如列之間的排水溝? 更改單個 CSS 變量的值並查看此更改在站點範圍內的反映。

完全動態的 calc() 函數:現在您可以在這些函數中使用自定義屬性來擁有完全動態的calc()函數,無需在 JavaScript 中進行複雜或短暫的計算,然後在每個實例上手動更新這些值。

為您的 CSS 文件注入新的活力

CSS 自定義屬性是一種強大且創新的方式,可為您的樣式錶帶來更多活力,它首次在 CSS 中引入了完全動態的值。

該規範目前處於候選推薦狀態,這意味著標準化指日可待,這是深入研究此功能並充分利用它的好理由。

  1. 注意:正如 Lea Verou 在 4 月 22 日指出的那樣,現在幾乎所有主流瀏覽器都默認支持自定義屬性,而無需切換標誌。 除非需要對舊瀏覽器版本的支持,否則它在生產中的使用是安全的。