酷播亮新聞
最棒的知識補給站

你應該掌握的CSS自定義屬性技術點

文章摘要: 只要屬性的值使用了CSS自定義屬性在CSS中使用已宣告的CSS自定義屬性

特別宣告:此篇文章內容來源於 @Ohans Emmanuel 的《 Everything you need to know about CSS Variables 》一文。

大多數程式語言都支援變數。但遺憾的是,CSS從一開始就缺乏對原生變數的支援。如果寫CSS的話,那是沒有變數的,除非你使用像Sass這樣的CSS處理器。

變數是Sass這樣處理器的一個非常有用的特性之一。這也是你嘗試使用的理由之一。Web技術發展是非常快速的。我很高興地告訴你,CSS現在終於支援原生的變數了。

雖然CSS處理器還支援更多的特性,但是CSS新增原生的變數是很好的。這些舉措使用Web更接近未來的技術。在這篇文章接下來的內容中,我將向你展示如何在CSS使用變數,以及如何使用它們讓你的工作變得更輕鬆。

特別宣告:爲了能讓CSS的原生變數與CSS處理器變數區分出來,我更喜歡將其稱為CSS自定義屬性。

你將學到

首先會向大家介紹CSS自定義屬性的基本知識。我相信試圖理解CSS自定義屬性都必須從這一點開始。學習CSS自定義屬性的基本知識是非常有意思的事情。其中更有趣的是,你可以在真實的專案中使用這些基本原理。

因此,我將通過三個簡單的專案來向你展示CSS自定義屬性的易用性。先來快速預覽一下這三個專案:

專案1:使用CSS自定義屬性建立元件變數

你可能在專案中已經使用到了元件變數。不管是React、Angular或者Vue中,使用CSS自定義屬性都會使這個過程變得更簡單。

專案2:使用CSS自定義屬性實現面板切換

你可能在某個地方看到過類似的效果。在這個專案中將向你展示使用CSS自定義屬性是如何簡單的為Web網站實現面板切換的效果。

專案3: 建立CSS自定義屬性展臺(Booth)

這是最後一個專案。請不要介意這個名字。說實在的,我想不出一個更好的名字了。

注意如何動態更新容器的顏色,以及如何在 inputtype="range" )控制條的範圍內更改外部容器的3D旋轉效果。

這個專案演示了使用JavaScript更新CSS自定義屬性的便利性,以及即改即得的效果。你可以在上面示例中的 input 框中輸入任意顏色值或者拖動 range 的進度條,瀏覽對應的效果變化。

為什麼CSS自定義屬性如此重要?

如果你是第一次接觸CSS處理器中的變數或者CSS自定義屬性,那麼接下來介紹的幾個方面將告訴你為什麼CSS自定義屬性對你而言是多麼的重要。

理由1:程式碼更具可讀性

不做過多的闡述,直接告訴你,使用CSS自定義屬性可以讓你的程式碼變得更具可讀性和可維護性。

理由2:在大型專案中更易於修改

如果你將所有常量儲存在一個單獨的檔案中,那麼你想對一個變數進行更改時,不必跳過數千行程式碼。它變得很寬鬆,你可以把它放在任何一個地方。

理由3:更暴打發現輸入錯誤

通過程式碼來查詢錯誤是一件極為痛苦的事情。特別是你的錯誤是由於一個簡單輸入引起的,那就更令人惱火了。因為它是極難被人發現。CSS自定義屬性的使用將消除這些麻煩。

為此,可讀性和可維護性是CSS自定義屬性最大的優勢。

我們需要感謝 CSS自定義屬性,讓我們可以在CSS中使用原生的變數,而不再需要藉助於類似Sass這樣的CSS處理器。

定義CSS自定義屬性

我們從一些熟悉的東西開始: JavaScript中的變數

一個簡單的JavaScript變數可以像下面這樣來宣告:

var amAwesome;

然後你可以給它賦值,比如:

amAwesome = "awesome string"

在CSS中,一個CSS自定義屬性是以兩個破折號( -- )開始的任何名稱。

/* 你可以在這裏宣告一個CSS自定義屬性*/
.block {
    color: #8cacea;
    --color: blue; /* 可以是常規的CSS屬性,但需要以兩個破折號(`--`)開始 */
}

CSS自定義屬性作用域

還有一件事你需要注意。

請記住,在JavaScript中,變數是有作用域一說。它們可能是全域性作用域,也有可能是區域性作用域。那麼在CSS中, CSS自定義屬性也有這樣的說法

比如下面這個示例:

:root {
    --main-color: red
}

:root 選擇器可以選擇到DOM元素中或 document 樹中最高頂級的元素。因此,在 :root 選擇器是宣告的CSS自定義屬性,其作用域的範圍是 全域性範圍 ,也就是全域性作用域。

明白了?

:root {
    --color: black; /* 全域性作用域*/
}

.block {
    color: #8cacea;
    --color: blue; /* 區域性作用域;`--color`作用域是`.block`選擇器 */
}

示例

假設你想建立一個CSS自定義屬性,該自定義屬性儲存Web網站面板的主色(Primary color)。那麼你將會怎麼做呢?

你將建立選擇器範圍。使用 :root 建立一個 global 自定義屬性:

:root {

}

然後宣告自定義屬性:

:root {
    --primary-color: red;
}

請記住,CSS自定義屬性可以是任何名稱,但名稱前必須要以兩個破折號,比如 --color

這是不是很簡單。

使用CSS自定義屬性

一旦宣告了一個CSS自定義屬性,並給其指定了一個值,那麼你就可以在CSS的屬性值中使用它。不過使用還是有點小問題。

如果你是在CSS處理器中使用,那麼你必須在屬性值中引用這個已宣告的變數,例如:

$font-size: 20px;

.test {
    font-size: $font-size;
}

但在CSS中使用已宣告的CSS自定義屬性,和在CSS處理器中使用宣告的變數略有不同。你需要通過 var() 函式來引用已宣告的CSS自定義屬性。

比如上面的示例,在CSS中使用已宣告的CSS自定義屬性,需要像下面這樣使用:

:root {
    --font-size: 20px; /* 宣告一個全域性使用域的CSS自定義屬性 */
}

.test {
    font-size: var(--font-size); /* 通過var()函式呼叫已宣告的CSS自定義屬性--font-size */
}

一旦你理解了這一點,你就會開始喜歡CSS自定義屬性,而且會很喜歡。

不過需要特別注意的是, CSS自定義屬性不像Sass(或其他CSS處理器)中的變數,可以在許多地方使用變數,並且可以進行一些數學運算,但使用CSS自定義屬性時,只能在CSS屬性值中使用CSS自定義屬性

/* 這是一種錯誤的使用方式 */
.margin {
    --side: margin-top;
    var(--size): 20px;
}

也不能像Sass這樣的處理器一樣直接做一些數學計算。如果你需要做一些資料計算,需要使用CSS的 calc() 函式。我們將在後續的示例中會聊到這一點。

/* 這是一種錯誤的使用方式 */
.margin {
    --space: 20px * 2;
    font-size: var(--space); 
}

使用CSS自定義屬性要做一些數學計算時,應該像下面這樣通過 calc() 函式來完成:

.margin {
    --space: calc(20px * 2);
    font-size: var(--space);
}

值得注意的地方

以下幾個點是值得一提的地方。

自定義屬性是普通屬性,可以在任意元素上宣告它們

CSS自定義屬性可以在任意元素上,比如 psectionaside 、根元素,甚至是偽元素上宣告。他們都會按照預期進行工作。

p {
    --color: blue;
}

section {
    --color: #bad;
}

aside {
    --color: yellow;
}

:root {
    --color: teal;
}

p:before {
    --color: red;
}

當你在對應的元素中呼叫相應的CSS自定義屬性時,可以看到他們都能按照你的預期工作:

CSS自定義屬性可以通過繼承和級聯規則來解決

比如下面這段示例程式碼:

div {
    --color: red;
}

div.test {
    color: var(--color)
}

div.ew {
    color: var(--color)
}

和正常變數一樣, --color 將會繼承 div 中的值:

CSS自定義屬性可以通過 @media 和其他條件規則來實現

和其他屬性一樣,可以在 @media 或 其他條件規則 中更改CSS自定義屬性的值。

比如下面這段示例程式碼,在較大的螢幕裝置上將會改變 gutter 的值:

:root {
    --gutter: 10px;
}

@media screen and (min-width: 768px) {
    --gutter: 30px;
}

CSS自定義屬性可以用在HTML元素的 style 屬性中

你可以選擇在內聯樣式中宣告CSS自定義屬性,它同樣是可以按照你的預期進行工作。





body {
    color: var(--color)
}

值得一提的是: CSS自定義屬性是區分大小寫的 。這一點需要特別的注意。

/* 這是兩個不同的CSS自定義屬性 */
:root {
    --color: blue;
    --COLOR: red;
}

解決多個宣告的CSS自定義屬性

CSS自定義屬性和其他CSS屬性一樣,可以用標準級聯解決多個相同宣告的CSS自定義屬性。比如下面這個示例:

/* 宣告相同名稱的CSS自定義屬性 */
:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }

/* 使用CSS自定義屬性 */
* { color: var(--color); }

就上面宣告的CSS自定義屬性,下列元素的文字顏色將會是什麼顏色呢?

What's my color?

and me?
What's my color too?

color?

你能基於上述的知識點猜出來結果嗎?

第一個

元素是 blue 。因為在 p 選擇器上沒有顯式定義 --color ,所以它將繼承來自 :root 中的 --color 的值。

:root { --color: blue; }

第一個

元素將是 green 。這一點非常的明顯,因為在 div 選擇器上顯示的宣告了 --color 自定義屬性的值為 green

div { --color: green; }

ID名為 #alertdiv 元素,它的顏色不再是 green ,將會是 red ,那是因為在 #alert 選擇器中也顯式的宣告了 --color 的值為 red :

#alert { --color: red; }

該ID選擇器直接宣告了一個自定義屬性的作用域,其定義的值將會覆蓋前面 div 宣告的自定義屬性,那是因為 #alert 選擇器的權重高於 div 選擇器。

由於最後一個

元素在 #alert 內,所以它的顏色也將是 red

p 元素上沒有顯式宣告CSS自定義屬性,但在 :root 元素上顯式的宣告了,因為正如你所期望的一樣,其顏色為 blue

:root { --color: blue; }

但CSS自定義屬性和CSS中的其他屬性是類似的,也具有繼承這樣的特性。所以最後一個

元素會繼承其父元素 #alert 中宣告的CSS自定義屬性值:

#alert { --color: red; }

解決迴圈依賴

迴圈依賴的發生方式如下。

當一個變數依賴於它自己。也就是說,它使用的是引用自身的 var()

:root {
    --m: var(--m)
}

body {
    margin: var(--m)
}

另外一種方式就是兩個或多個變數相互引用時:

:root {
    --one: calc(var(--two) + 10px);
    --two: calc(var(--one) - 10px);
}

目前唯一可破的方法是: 不要在程式碼中建立具有迴圈依賴關係的CSS自定義屬性

無效的CSS自定義屬性將會發生什麼?

如果是語法錯誤,將會直接視為無效,但無效的 var() 將會被該屬性的初始值或繼承值替代。比如下面的示例:

:root { 
    --color: 20px; 
}
p { 
    background-color: red; 
}
p { 
    background-color: var(--color);  /* 設定了一個無效的顏色值 */
}

如你所預期的一樣, --colorvar() 替換了,但是屬性值 background-color:20px 是一個無效值。由於 background-color 不是一個可繼承的屬性,所以該值將預設為 background-color 的初值值 transparent

請注意,如果你已經寫了 background-color: 20px 沒有自定認屬性來替換,那麼 background-clor 將是無效的。要是前面有對應的宣告,將會使用前面的宣告。

在構建單個指令時要小心

當你設定如下所示的屬性值時, 20px 被解釋為單個指令(Tokens)。

font-size: 20px

一個簡單的方法是, 20px 的值被視為一個單獨的實體。在使用CSS自定義屬性構建單個指令時,需要特別的小心。比如下面這段示例程式碼:

:root {
    --size: 20
}

div {
    font-size: var(--size)px /* 錯誤使用 */
}

你可能已經預料到 font-size 的值會產生 20px ,但這是錯誤的使用方式。瀏覽器會將其解釋為 20 px 注意 20px 之間有一個空格

因此,如果你必須建立單個指令,則用一個CSS自定義屬性來表示整個指令,比如 --size:20px 或者使用 calc() 函式,比如 calc(var(--size) * 1px) (當 --size 設定為 20 時)。

如果你對這一點不怎麼理解,沒關係,在接下來的示例中會詳細的解釋這部分內容。

我們來動手做點東西

這是我們這篇文章中一直期待的一部分。將能過構建一些有用的專案來實踐前面所討論到的相關概念。還等什麼呢?我們開始吧。

使用CSS自定義屬性建立元件變數

假設我們要建立兩個不同的按鈕。這兩個按鈕的樣式基本相同,只是略有一些細節不一樣。

在這個示例中,只有 background-colorborder-color 樣式不同。如果你來做,你將會怎麼做呢?這就是典型的解決方案。

建立一個基類,比如說 .btn 並新增變化的類。這個示例的結構如下:


.btn 基類涵蓋了按鈕的基本樣式。比如:

.btn {
    padding: 2rem 4rem;
    border: 2px solid black;
    background: transparent;
    font-size: 0.6em;
    border-radius: 2px;
}

.btn:hover {
    cursor: pointer;
    background: black;
    color: white;
}

那麼,對於略有差異的按鈕效果怎麼來實現呢?看下面的程式碼:

.btn.red {
    border-color: red
}
.btn.red:hover {
    background: red
}

你知道我們是如何複製程式碼的吧。不過我們使用CSS自定義屬性來做會做得更好。那麼要做的第一步將是什麼呢?

使用CSS自定義屬性替換不同的顏色,但不要忘記為其新增預設值。

.btn {
    padding: 2rem 4rem;
    border: 2px solid var(--color, black);
    background: transparent;
    font-size: 0.6em;
    border-radius: 2px;
}

.btn:hover {
    cursor: pointer;
    background: var(--color, black);
    color: white;
}

當你設定 background:var(--color,black) 時,其意思就是 background 的值是CSS自定義屬性 --color 的值。當 --color 不存在時,就會使用其預設值 black

這就是給CSS自定義屬性設定預設值的方法。就像JavaScript或其他程式語言一樣。這樣使用是很有意義的。

對於有差異的按鈕,你只需要像下面這樣提供CSS自定義屬性的新值就可以:

.btn.red {
    --color: red
}

這就是兩個按鈕所有的樣式程式碼。現在,當你使用 .red 類名時,瀏覽器會解析出不同的顏色值,並立即更新按鈕的樣式效果。

如果你花大量時間構建可重用的元件,像這樣使用CSS自定義屬性就會很方便。來看看他們之間對比的截圖:

如果在你的元件庫中,還有其他風格的按鈕效果,使用CSS自定義屬性,你就可以省去很多額外的時間:

使用CSS自定義屬性切換Web站點的面板

切換Web網站的面板效果,我想你以前肯定有碰到過。比如像下面這樣的效果:

那麼這樣的一個效果,使用CSS自定義屬效能有多簡單呢?我們來一起看看。

在此之前,我想先提一下,這個例子非常的重要。在這個示例中,將會涉及到使用JavaScript更新CSS自定義屬性的一個方法。

我們真正想做的

CSS自定義屬性美妙之處在於它們的響應性。一旦它們被更新,只要屬性的值使用了CSS自定義屬性,就將會被更新。

從概念上講,下面這張圖,能很好的解釋整個過程。

因此,需要通過JavaScript給按鈕新增點選事件的監聽。

對於這個簡單的示例,都是基於CSS自定義屬性來對整個頁面的背景顏色和文字顏色做切換。也就是說,當用戶點選上面的任一按鈕時,他們將CSS自定義屬性設定為其他顏色。因此,頁面的背景顏色和文字顏色會做相應的變化,從而實現切換面板的效果。

模板結構

頁面所需的模板結果如下:

...

.theme 容器中包含了三個 button 。另外爲了節約篇幅,把 article 元素中的內容省略了。

頁面樣式

這個專案的成功之處就是頁面的樣式。而其中的訣竅又很簡單。我們沒有直接設定 background-colorcolor 的值,而是基於CSS自定義屬性來給他們設定屬性值。下面就是我想要表達的意思:

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

要實現切換面板的效果,原因很簡單。每當單擊一個按鈕時,將要更改 body 中對應的兩個CSS自定義屬性的值。在更改之後,頁面的整體樣式將被更新。是不是非常的簡單。

接下來,我們看看怎麼通過JavaScript來實現CSS自定義屬性值的更新。

新增JavaScript程式碼

下面是這個示例效果所需的所有JavaScript程式碼:

const root = document.documentElement 
const themeBtns = document.querySelectorAll('.theme > button')

themeBtns.forEach((btn) => {
    btn.addEventListener('click', handleThemeUpdate)
})

function handleThemeUpdate(e) {
    switch(e.target.value) {
        case 'dark': 
            root.style.setProperty('--bg', 'black')
            root.style.setProperty('--bg-text', 'white')
            break
        case 'calm': 
            root.style.setProperty('--bg', '#B3E5FC')
            root.style.setProperty('--bg-text', '#37474F')
            break
        case 'light':
            root.style.setProperty('--bg', 'white')
            root.style.setProperty('--bg-text', 'black')
            break
    }
}

看到上面這一坨JavaScript程式碼,千萬別嚇到你。事實上這比你想像的要簡單得多。

首先,通過 const root = document.documentElement 來獲取根元素。這裏的根元素指的就是 元素。明白這一點是非常重要的。如果你感到好奇,這並奇怪,因為它需要設定CSS自定義屬性的新值。

同樣的,可以通過 const themeBtns = document.querySelectorAll('.theme > button') 選到 .theme 元素下的所有 button 元素。 querySelectorAll 會生成一個類似陣列的數據結構,需要對這個陣列進行迴圈遍歷。遍歷每個按鈕,並給其新增一個單擊事件監聽器。具體方法如下:

themeBtns.forEach((btn) => {
    btn.addEventListener('click', handleThemeUpdate)
})

接下來我們解釋一下 handleThemeUpdate 函式。每個按鈕補點選時都會有一個 handleThemeUpdate 作為它的回撥函式。注意,什麼按鈕被點選,然後執行正確的操作變得非常重要。

在此基礎上,使用了一個 operator 開關器,並根據被單擊的按鈕的值執行一些操作。現在你再看一下JavaScript程式碼,你就能很輕易的理解它了。

構建CSS自定義屬性展臺

接下來我們將要構建一個CSS自定義屬性展臺:

記住,盒子的顏色是動態更新的,並且盒子的容器在三維空間中旋轉,而且是隨著 range 輸入的值做想應的角度旋轉:

你可以在文章前面的示例中體驗一下案例的效果。這是使用JavaScript更新CSS自定義屬性的典型案例之一。

接下來,咱們一起看看這個案例是怎麼實現的。

模板結構

以下是所需的元件:

  • 一個 range 的輸入框
  • 存放指令的容器
  • 包含其他輸入框的容器,以及每個輸入框所包含的輸入欄位

結構很簡單:

有幾個方面需要注意:

  • input type=range 的值的範圍是 -5050 ,每次移動的值是 5 ,其最小輸入值為 -50
  • 如果你不確定這個 range 輸入是如何工作的,可以先查閱相關的文件
  • 請注意如何使用 .color-boxes.color-box 容器類名,在這些容器中存在 input
  • 值得一提的是,第一個 input 的預設值是 red

瞭解了文件的結構之後,就可以這樣做了:

  • .slider.instructions 容器設定為絕對定位,讓其脫離文件流
  • body 元素設定一個 background-color ,並且在其左下角新增一個花的背景圖
  • .color-boxes 容器放置在頁面的正中心
  • .color-boxes 容器新增樣式

先做這些處理吧。

/* Slider */
.slider,
.instructions {
    position: absolute;
    background: rgba(0,0,0,0.4);
    padding: 1rem 2rem;
    border-radius: 5px
}
.slider {
    right: 10px;
    top: 10px;
}
.slider > * {
    display: block;
}


/* Instructions */
.instructions {
    text-align: center;
    bottom: 0;
    background: initial;
    color: black;
}

程式碼並不像你想像的那麼複雜。我希望你能理解它。如果你不理解上面的程式碼,那麼你可以通過下面的評論與我一起交流和討論。

對於 body 的效果需要更多的程式碼。由於我們使用 background-colorbackground-image 來給 body 設定樣式。所以使用 background 的簡寫屬性來設定多個背景可能是最好的一種選擇。

body {
    margin: 0;
    color: rgba(255,255,255,0.9);
    background: url('http://bit.ly/2FiPrRA') 0 100%/340px no-repeat, var(--primary-color);
    font-family: 'Shadows Into Light Two', cursive;
}

url 指向的是向日葵圖片的地址,接下來的一組屬性 0 100% 表示背景影象的位置。接下來的內容簡單的介紹了CSS背景影象定位的基本原理。

/ 後的另一部分表示 background-size 的值。如果你把這個值縮小,那麼背景影象也會相應的縮小。 no-repeat 你可能知道其意思。它用來防止背景影象不重複鋪滿 body 元素。最後,逗號後面的任何東西都是用來宣告第二個背景的。在我們這個示例中,第二個背景只設置了一個背景顏色,而且其值是 var(--primary-color)

你一看就知道,它就是一個CSS自定義屬性。這也意味著你必須先宣告這個CSS自定義屬性。比如:

:root {
    --primary-color: rgba(241,196,15 ,1)
}

--primary-color 的原值是 yellow 。這沒什麼大不了的,接下來我們很快會在那裏設定更多的CSS自定義屬性。現在我們要做的是將 .color-boxes 放到頁面的正中間:

main.booth {
    min-height: 100vh;

    display: flex;
    justify-content: center;
    align-items: center;
}

main 容器是一個Flex容器,並正確地將其子元素設定到頁面的正中心位置。另外再把 .color-boxes 和他的子元素做得更好看一點。

.color-box {
    padding: 1rem 3.5rem;
    margin-bottom: 0.5rem;
    border: 1px solid rgba(255,255,255,0.2);
    border-radius: 0.3rem;
    box-shadow: 10px 10px 30px rgba(0,0,0,0.4); 
}

設定了一個陰影效果。效果看上去有一些酷酷的感覺。咱們繼續給 .color-boxes 容器新增一些樣式:

.color-boxes {
    background: var(--secondary-color);
    box-shadow: 10px 10px 30px rgba(0,0,0,0.4);
    border-radius: 0.3rem;

    transform: perspective(500px) rotateY( calc(var(--slider) * 1deg));
    transition: transform 0.3s
}

又是一坨程式碼,感覺好複雜的樣子。事實上將其拆分一下,就會顯得簡單得多。

.color-boxes {
    background: var(--secondary-color);
    box-shadow: 10px 10px 30px rgba(0,0,0,0.4);
    border-radius: 0.3rem;
}

你知道這是什麼嗎?在這裏有一個新的CSS自定義屬性,我們應該將其新增到 :root 選擇器中。

:root {
    --primary-color: rgba(241,196,15 ,1);
    --secondary-color: red;
}

第二種顏色是 red 。這將給容器設定一個 red 背景色。

接下來的程式碼可能會讓部分同學感到困惑:

.color-boxes {
    transform: perspective(500px) rotateY( calc(var(--slider) * 1deg));
    transition: transform 0.3s
}

暫時,我們可以簡化上面的 transform 屬性的值。

例如:

transform: perspective(500px) rotateY( 30deg);

transform 使用了兩個不同的函式。一個是 perspective() ,另一個是 rotateY() 。那麼這兩個函式有什麼作用呢?

perspective() 函式應用於3D空間中被變換的函式。它將啟用三維空間,並在 z 軸上賦予元素深度。

有關於 perspective() 這方面更多的資料,你可以點選 這裏 或這裏進行了解。

rotateY() 函式又是怎麼一回事呢?通過 perspective() 函式啟用的三維空間中,元素有 xyz 等平面,其中 rotateY() 函式會讓元素沿著 y 平面旋轉。

下圖來自於 codrops 的圖,能更好的幫助你理解這方面相關的知識。

有關於 transform 方面更多的介紹,可以點選這裏進行了解。

我希望這些能幫助你消除一些壓力。那我們回到開始的地方吧。

當你移動滑塊時,你知道什麼函式會影響 .container-box 的旋轉嗎?

它會被呼叫的 rotateY() 函式,讓這個盒子沿著 Y 軸旋轉。由於傳入 rotateY() 函式的值將是通過JavaScript來更新,因此它的值應該用一個CSS自定義屬性來表示。

那麼為什麼用 1deg 乘以這個CSS自定義屬性呢?

從經驗上來說,建議構建單一的指令時,將值儲存在沒有帶單位的CSS自定義屬性中。然後通過 calc() 函式將它們轉換成任何你想要的單位。

當你有這些值的時候,你可以用這些值做任何你想做的事情。想要轉換成 degvw ,你都可以任意選擇。

在這種情況下,通過將 number 值乘以 1deg 來把數字轉換成帶有單位的值。

由於CSS是不理解數學計算的,所以你必須通過 calc() 函式來完成。一旦完成,我們就變得容易多了。這個變數的值可以在JavaScript中進行更新。

對於CSS來說,現在只剩下一點點了。

.color-box:nth-child(1) {
    background: var(--bg-1)
}
.color-box:nth-child(2) {
    background: var(--bg-2)
}
.color-box:nth-child(3) {
    background: var(--bg-3)
}
.color-box:nth-child(4) {
    background: var(--bg-4)
}
.color-box:nth-child(5) {
    background: var(--bg-5)
}
.color-box:nth-child(6) {
    background: var(--bg-6)
}

首先使用 :nth-child 選擇器來選擇每個子元素。

這裏你需要有一些遠見。我們知道我們將更新每個盒子的背景顏色。我們還知道,這個背景顏色必須由一個CSS自定義屬性來表示,所以它可以通過JavaScript來訪問。對吧。

因此,我們可以這樣做:

.color-box:nth-child(1) {
    background: var(--bg-1)
}

非常容易的一件事。不過有一個問題。如果這個變數不存在,又會發生什麼呢?根據前面介紹的內容,針對這一問題,我們需要做一個降級處理。就是新增一個預設顏色,比如像下面這樣:

.color-box:nth-child(1) {
    background: var(--bg-1, red)
}

在這個特殊的案例中,我選擇不提供任何的降級處理。

如果在屬性值中使用CSS自定義屬性無效,則該屬性將接受其初始值。這一點前面已經提到過了。因此,當 --bg-1 無效或不可用時, background 將預設為其初始值 transparent .

初始值是指當屬性沒有顯式設定時的值。例如,如果不設定元素的背景顏色,它將預設為 transparent 。初始值是一種預設的屬性值。

加入一些JavaScript程式碼

對於JavaScript程式碼,我們要做的事情會很少。

首先讓我們來處理滑塊。僅只需要五行程式碼就可以了。

const root = document.documentElement
const range = document.querySelector('.booth-slider')

range.addEventListener('input', handleSlider)

function handleSlider (e) {
    let value = e.target.value 
    root.style.setProperty('--slider', value)
}

這對你而言是不是很簡單,對吧。

首先,通過 const range = document.querySelector('.booth-slider') 選到了滑塊元素。然後使用 range.addEventListener('input', handleSlider)input 元素新增一個監聽事件,當 input 的範圍值得到改變時,將會呼叫 handleSlider 回撥函式。

接下來做的就是編寫 handleSlider 回撥函式:

function handleSlider (e) {
    let value = e.target.value 
    root.style.setProperty('--slider', value)
}

root.style.setProperty('--slider', value) 的意思是獲取根元素的 style 樣式,然後設定其屬性值。

處理顏色變化

就像處理滑塊值的變化一樣簡單。

const inputs = document.querySelectorAll('.color-box > input')

inputs.forEach(input => {
    input.addEventListener('input', handleInputChange)
})

function handleInputChange (e) {
    let value = e.target.value
    let inputId = e.target.parentNode.id 
    let inputBg = `--bg-${inputId}` 
    root.style.setProperty(inputBg, value)
}

通過 const inputs = document.querySelectorAll('.color-box > input') 獲取所有 input 元素。然後給所有 input 設定一個事件監聽器:

inputs.forEach(input => {
    input.addEventListener('input', handleInputChange)
})

handleInputChange 回撥函式:

function handleInputChange (e) {
    let value = e.target.value
    let inputId = e.target.parentNode.id 
    let inputBg = `--bg-${inputId}` 
    root.style.setProperty(inputBg, value)
}

唷,唷,唷…….就是這麼的簡單。全部搞定!

還錯過了什麼

當我注意到我在任何地方都沒有提到瀏覽器對CSS自定義屬性的支援時,我已經完成了這篇文章的初稿。現在也該來收拾一下相應的殘局了。

瀏覽器對CSS自定義屬性的支援並不壞。可以說相當的不錯,到目前為止所有的現代瀏覽器中都對CSS自定義屬性做了良好的支援。在寫這篇文章的時候,已經超過87%了。

那麼問題來了,我現在可以在專案中使用CSS自定義屬性了?我的回答是的!不過,一定要檢查一下你自己的使用者群體。

值得慶幸的是,你可以使用 Myth 這樣的處理器。它將把一些CSS未來的特性做了相應的處理。言外之意,還未支援的CSS特性,你現在就可以使用,聽起來是不是很爽。難道不是嗎?

如果你有使用 PostCSS 的經驗,那麼這同樣是使用未來CSS的一個很好的方法。這裏有一個 CSS自定義屬性的PostCSS模組 。

如果你從未接觸過PostCSS相關的東西,那麼你有必要花點時間去了解或者學習一下了。

那今天就到這裏吧。這就是我要和大家聊的東西,有關於CSS自定義屬性,應該掌握的一些知識點。

大漠

常用暱稱「大漠」,W3CPlus創始人,目前就職於手淘。對HTML5、CSS3和Sass等前端指令碼語言有非常深入的認識和豐富的實踐經驗,尤其專注對CSS3的研究,是國內最早研究和使用CSS3技術的一批人。CSS3、Sass和Drupal中國佈道者。2014年出版《 圖解CSS3:核心技術與案例實戰 》。

如需轉載,煩請註明出處: https://www.w3cplus.com/css/everything-you-need-to-know-about-css-variables.html

如有侵權請來信告知:酷播亮新聞 » 你應該掌握的CSS自定義屬性技術點