[譯] 關於 CSS 變量,你須要瞭解的一切

本文是我新寫的電子書的第一章(電子書目前已支持 pdf 和 mobi 格式下載)。css

大多數編程語言都支持變量。然而遺憾的是,CSS 從一開始就缺少對原生變量的支持。html

你寫 CSS 嗎?若是寫的話你就知道是無法使用變量的。固然了,除非你使用像 Sass 這樣的預處理器。前端

像 Sass 這樣的預處理器是把變量的使用做爲一大亮點。這是一個很是好的理由去嘗試使用這類預處理器。固然了,這個理由已然足夠好了。android

Web 技術發展是很是快的,在此我很高興地報告 如今 CSS 支持變量了ios

然而預處理器還支持更多優秀特性,CSS 變量僅僅是其中之一。這些特性使得 Web 技術更加貼近將來。git

這篇指南將向你展現變量是如何在原生 CSS 中工做的,以及怎樣使用變量讓你的編程工做更輕鬆。github

你將學到

首先我將帶你粗略過一遍 CSS 變量的基礎知識。我相信任何理解 CSS 變量的嘗試都必須從這裏開始。npm

學習基礎知識是一件很是酷的事。更酷的是使用基礎知識來構建一個真正的應用。編程

所以,我將構建三個可以體現 CSS 變量的使用及其易用性的項目,用這種方式把兩件事結合起來。下面是對這三個項目的快速預覽。後端

項目 1: 使用 CSS 變量建立一個有變化效果的組件

你可能已經構建過一個有變化效果的組件了。不管你是使用 React,Angular 仍是 Vue,使用 CSS 變量都會讓構建過程更簡單。

使用 CSS 變量建立一個有變化效果的組件。

能夠在 Codepen 上查看這個項目。

項目 2: 使用 CSS 變量實現主題定製

可能你已經看過這個項目了。我會向你展現使用 CSS 變量來定製全站主題有多麼容易。

使用 CSS 變量定製全站主題。

能夠在 Codepen 上查看這個項目。

項目 3: 構建 CSS 變量展位

這是最後一個項目了,不要在乎這個項目名,我想不出更好的名字了。

盒子的顏色是動態更新的。

請注意盒子的顏色是如何動態更新的,以及盒子容器是如何隨着輸入範圍值的變化進行 3D 旋轉的。

.

這個項目展現了使用 JavaScript 更新 CSS 變量的便利性,從中你還會嚐到響應式編程的甜頭。

這會是很是好玩的!

花點時間在 Codepen 上玩一玩。

注意:本文假定你對 CSS 已得心應手。若是你對 CSS 掌握地不是很好,或者想學習如何創做出驚豔的 UI 效果,我建議你去學習個人 CSS 進階課程(共 85 課時的付費課程)。本文內容是該課程的一個節選。😉

爲什麼變量如此重要

若是你對預處理器和原生 CSS 中的變量並不熟悉的話,如下幾個緣由能夠爲你解答爲什麼變量如此重要。

緣由 #1:使得代碼更可讀

無需多言,你就能夠判斷出,變量使得代碼可讀性更好,更易於維護。

緣由 #2:易於在大型文檔中進行修改

若是把全部的常量都維護在一個單獨文件中,想改動某一變量時就無需在上千行代碼間來回跳轉進行修改。

這變得很是容易,僅僅在一個地方進行修改,就搞定了。

緣由 #3:定位打字錯誤更快

在多行代碼中定位錯誤很是痛苦,更痛苦的是錯誤是由打字錯誤形成的,它們很是難定位。善於使用變量能夠免除這些麻煩。

至此,可讀性和可維護性是主要優勢。

感謝 CSS 變量,如今咱們在原生 CSS 中也能享受到以上這些優勢了。

定義 CSS 變量

先以你已經很熟悉的東西開始:JavaScript 中的變量。

JavaScript 中,一個簡單的變量聲明會像這樣:

var amAwesome;
複製代碼

而後你像這樣能夠賦值給它:

amAwesome = "awesome string"
複製代碼

在 CSS 中,以兩個橫線開頭的「屬性」都是 CSS 變量。

/*你能夠找到變量嗎? */
.block {
 color: #8cacea;
--color: blue
}
複製代碼

CSS 變量也被稱爲「自定義屬性」。

CSS 變量做用域

還有一點須要注意。

請記住 JavaScript 中變量是有做用域的,要麼是全局做用域,要麼就是局部做用域

CSS 變量也是如此。

思考一下下面這個例子:

:root {
  --main-color: red
}
複製代碼

:root 選擇器容許你定位到 DOM 中的最頂級元素或文檔樹。

因此,這種方式聲明的變量就屬於具備全局做用域的變量。

明白了嗎?

局部變量與全局變量。

示例 1

假設你想建立一個 CSS 變量來存儲站點的主題顏色。

你會怎麼作呢?

  1. 建立一個做用域選擇器。經過 :root 建立一個全局變量。
:root {

}
複製代碼
  1. 定義變量
:root {
 --primary-color: red
}
複製代碼

請記住,在 CSS 中,以兩個橫線開頭的「屬性」都是 CSS 變量,好比 --color

就是這麼簡單。

使用 CSS 變量

變量一旦被定義並賦值,你就能夠在屬性值內使用它了。

可是有個小問題。

若是你用過預處理器的話,必定已經習慣經過引用變量名來使用該變量了。好比:

$font-size: 20px

.test {
  font-size: $font-size
}
複製代碼

原生 CSS 變量有些不一樣,你須要經過 var() 函數來引用變量。

在上面這個例子中,使用 CSS 變量就應該改爲這樣:

:root {
  --font-size: 20px
}

.test {
  font-size: var(--font-size)
}
複製代碼

兩種寫法大不同。

請記得使用 var 函數。

一旦你習慣了這種方式,就會愛上 CSS 變量的。

另外一個重要的注意事項是,在 Sass 這類預處理器中,你能夠在任意地方使用變量,作各類計算,可是須要注意,在原生 CSS 中,你只能將變量設置爲屬性值。

/*這是錯的*/
.margin {
--side: margin-top;
var(--side): 20px;
}
複製代碼

因爲屬性名非法,這段聲明會拋出語法錯誤

CSS 變量也不能作數學計算。若是須要的話,能夠經過 CSS 的 calc() 函數進行計算。接下來咱們會經過示例來闡述。

/*這是錯的*/
.margin {
--space: 20px * 2;
font-size:  var(--space);  // 並不是 40px
}
複製代碼

若是你必需要作數學計算的話,能夠像這樣使用 calc() 函數:

.margin {
--space: calc(20px * 2);
font-size:  var(--space);  /*等於 40px*/
}
複製代碼

關於屬性的一些事

如下是幾個須要闡述的屬性行爲:

1. 自定義屬性就是普通屬性,能夠在任意元素上聲明自定義屬性

在 p,section,aside,root 元素,甚至僞元素上聲明自定義屬性,均可以運行良好。

這些自定義屬性工做時與普通屬性無異。

2. CSS 變量由普通的繼承與級聯規則解析

請思考如下代碼:

div {
  --color: red;
}

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

div.ew {
  color: var(--color)
}
複製代碼

像普通變量同樣,--color 的值會被 div 元素們繼承。

3. CSS 變量能夠經過 @media 和其它條件規則變成條件式變量

和其它屬性同樣,你能夠經過 @media 代碼塊或者其它條件規則改變 CSS 變量的值。

舉個例子,如下代碼會在大屏設備下改變變量 gutter 的值。

:root {
 --gutter: 10px
}

@media screen and (min-width: 768px) {
    --gutter: 30px
}
複製代碼

對於響應式設計頗有用。

4. HTML 的 style 屬性中可使用 CSS 變量。

你能夠在行內樣式中設置變量值,變量依然會如期運行。

<!--HTML-->
<html style="--color: red">

<!--CSS-->
body {
  color: var(--color)
}
複製代碼

行內設置變量值。

要注意這一點,CSS 變量是區分大小寫的。我爲了減少壓力,選擇都採用小寫形式,這件事見仁見智。

/*這是兩個不一樣的變量*/
:root {
 --color: blue;
--COLOR: red;
}
複製代碼

解析多重聲明

與其它屬性相同,多重聲明會按照標準的級聯規則解析。

舉個例子:

/*定義變量*/
:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }

/*使用變量*/
* { color: var(--color); }
複製代碼

根據以上的變量聲明,下列元素是什麼顏色?

<p>What's my color?</p> <div>and me?</div> <div id='alert'> What's my color too?
  <p>color?</p>
</div>
複製代碼

你想出答案了嗎?

第一個 p 元素顏色是 藍色p 選擇器上並無直接的顏色定義,因此它從 :root 上繼承屬性值

:root { --color: blue; }
複製代碼

第一個 div 元素顏色是 綠色。這個很簡單,由於有變量直接定義在 div 元素上

div { --color: green; }
複製代碼

具備 ID 爲 alertdiv 元素顏色不是綠色,而是 紅色

#alert { --color: red; }
複製代碼

因爲有變量做用域直接是在這個 ID 上,變量所定義的值會覆蓋掉其它值。#alert 選擇器是一個更爲特定的選擇器。

最後,#alert 元素內的 p 元素顏色是 紅色

這個 p 元素上並無變量聲明。因爲 :root 聲明的顏色屬性是 藍色,你可能會覺得這個 p 元素的顏色也是 藍色

:root { --color: blue; }
複製代碼

如其它屬性同樣, CSS 變量是會繼承的,所以 p 元素的顏色值繼承自它的父元素 #alert

#alert { --color: red; }
複製代碼

小測驗的答案。

解決循環依賴

循環依賴會出如今如下幾個場景中:

  1. 當一個變量依賴本身自己時,也就是說這個變量經過 var() 函數指向本身時。
:root {
  --m: var(--m)
}

body {
  margin: var(--m)
}
複製代碼
  1. 兩個以上的變量互相引用。
:root {
  --one: calc(var(--two) + 10px);
  --two: calc(var(--one) - 10px);
}
複製代碼

請注意不要在你的代碼中引入循環依賴。

使用非法變量會怎樣?

語法錯誤機制已被廢棄,非法的 var() 會被默認替換成屬性的初始值或繼承的值。

思考一下下面這個例子:

:root { --color: 20px; }
p { background-color: red; }
p { background-color: var(--color); }
複製代碼

正如咱們所料,--color 變量會在 var() 中被替換,可是替換後,屬性值 background-color: 20px 是非法的。因爲 background-color 不是可繼承的屬性,屬性值將默認被替換成它的初始值即 transparent

注意,若是你沒有經過變量替換,而是直接寫 background-color: 20px 的話,這個背景屬性聲明就是非法的,則使用以前的聲明定義。

當你本身寫聲明時,狀況就不同了。

使用單獨符號時要當心

當你用下面這種方式來設置屬性值時,20px 則會按照單獨符號來解析。

font-size: 20px
複製代碼

有一個簡單的方法去理解,20px 這個值能夠看做是一個單獨的 「實體」。

在使用 CSS 變量構建單獨符號時須要很是當心。

舉個例子,思考如下代碼:

:root {
 --size: 20
}

div {
  font-size: var(--size)px /*這是錯的*/
}
複製代碼

可能你會覺得 font-size 的值是 20px,那你就錯了。

瀏覽器的解釋結果是 20 px

請注意 20 後面的空格

所以,若是你必須建立單獨符號的話,請用變量來表明整個符號。好比 --size: 20px,或者使用 calc 函數好比 calc(var(--size) * 1px) 中的 --size 就是等於 20

若是你沒看懂的話也不用擔憂,在下個示例中我會解釋地更詳細。

一顆賽艇!

如今咱們已經到了期待已久的章節了。

我將經過構建幾個有用的小項目,在實際應用中引導你瞭解以前所學的理論。

讓咱們開始吧。

項目 1: 使用 CSS 變量建立一個有變化效果的組件

思考一下須要構建兩個不一樣按鈕的場景,兩個按鈕的基本樣式相同,只有些許不一樣。

這個場景中,按鈕的 background-colorborder-color 屬性不一樣。

那麼你會怎麼作呢?

這裏有一個典型解決方案。

建立一個叫 .btn 的基礎類,而後加上用於變化的類。舉個例子:

<button class="btn">Hello</button>
<button class="btn red">Hello</button>
複製代碼

.btn 包括了按鈕上的基礎樣式,如:

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

/*hover 狀態下*/
.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;
 }

 /*hover 狀態下*/
 .btn:hover {
  cursor: pointer;
   background: var(--color, black);
   color: white;
 }
複製代碼

當你寫下 background: **var(--color, black)** 時,就是將背景色的值設置爲變量 --color 的值,若是變量不存在的話則使用默認值 **black**

這就是設置變量默認值的方法,與在 JavaScript 和其它語言中的作法同樣。

這是使用變量的好處。

使用了變化量,就能夠用下面這種方法來應用變量的新值:

.btn.red {
   --color: red
 }
複製代碼

就是這麼簡單。如今當使用 .red 類時,瀏覽器注意到不一樣的 --color 變量值,就會當即更新按鈕的樣式了。

若是你要花不少時間來構建可複用組件的話,使用 CSS 變量是一個很是好的選擇。

這是並排比較:

不用 CSS 變量 VS 使用 CSS 變量。

若是你有很是多的可變選項的話,使用 CSS 變量還會爲你節省不少打字時間。

看出不一樣了嗎??

項目 2: 使用 CSS 變量實現主題定製

我很肯定你以前必定遇到過主題定製的需求。支持主題定製的站點讓用戶有了自定義的體驗,感受站點在本身的掌控之中。

下面是我寫的一個簡單示例:

使用 CSS 變量來實現有多麼容易呢?

咱們來看看。

在此以前,我想提醒你,這個示例很是重要。經過這個示例我將引導你理解使用 JavaScript 更新 CSS 變量的思想。

很是好玩!

你會愛上它的!

咱們究竟想作什麼。

CSS 變量的美在於其本質是響應式的。一旦 CSS 變量更新了,任意帶有 CSS 變量的屬性的值也都會隨之更新。

從概念上講,下面這張圖解釋了這個示例的流程。

流程。

所以,咱們須要給點擊事件監聽器寫一些 JavaScript 代碼。

在這個簡單的示例裏,文本與頁面的顏色和背景色都是基於 CSS 變量的。

當你點擊頁面上方的按鈕時,JavaScript 會將 CSS 變量中的顏色切換成別的顏色,頁面的背景色也就隨之更新。

這就是所有了。

還有一件事。

當我說 CSS 變量切換成別的顏色時,是怎麼作到的呢?

行內設置變量。

即便是在行內設置,CSS 變量也會生效。在 JavaScript 中,咱們控制了文檔的根節點,而後就能夠在行內給 CSS 變量設置新的值了。

明白了嗎?

咱們說了太多了,如今該幹些實際的了。

結構初始化

初始化結構是這樣的:

<div class="theme">
  <button value="dark">dark</button>
  <button value="calm">calm</button>
  <button value="light">light</button>
</div>

<article>
...
</article>
複製代碼

結構中有三個父元素爲 .theme 的按鈕元素。爲了看起來儘量簡短,我將 article 元素內的內容截斷了。article 元素內就是頁面的內容。

設置頁面樣式

項目的成功始於頁面的樣式。這個技巧很是簡單。

咱們設置頁面樣式的 background-colorcolor 是基於變量的,而不是寫死的屬性值。

這就是我說的:

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

這麼作的緣由顯而易見。不管什麼時候按鈕被點擊,咱們都會改變文檔中兩個變量的值。

根據變量值的改變,頁面的總體樣式也就隨之更新。小菜一碟。

讓咱們繼續前進,解決在 JavaScript 中更新屬性值的問題。

進入 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
  }
}
複製代碼

不要被這段代碼嚇到,它比你想象的要簡單。

首先,保存一份對根節點的引用, const root = document.documentElement

這裏的根節點就是 HTML 元素。你很快就會明白爲何這很重要。若是你很好奇的話,我能夠先告訴你一點,給 CSS 變量設置新值時須要根節點。

一樣地,保存一份對按鈕的引用, const themeBtns = document.querySelectorAll('.theme > button')

querySelectorAll 生成的數據是能夠進行遍歷的類數組結構。遍歷按鈕,而後給按鈕設置點擊事件監聽。

這裏是怎麼作:

themeBtns.forEach((btn) => {
  btn.addEventListener('click', handleThemeUpdate)
})
複製代碼

handleThemeUpdate 函數去哪了?咱們接下來就會討論這個函數。

每一個按鈕被點擊後,都會調用回調函數 handleThemeUpdate。所以知道是哪一個按鈕被點擊以及後續該執行什麼正確操做很重要。

鑑於此,咱們使用了 switch 操做符,基於被點擊的按鈕的值來執行不一樣的操做。

接下來再看一遍這段 JavaScript 代碼,你會理解地更好一些。

項目 3: 構建 CSS 變量展位

避免你錯過它,這是咱們即將構建的項目:

請記住盒子的顏色是動態更新的,以及盒子容器是隨着輸入範圍值的變化進行 3D 旋轉的。

你能夠直接在 Codepen 上玩一下這個項目。

這是使用 JavaScript 更新 CSS 變量以及隨之而來的響應式特性的絕佳示例。

讓咱們來看看如何來構建。

結構

如下是所需的組件。

  1. 一個範圍輸入框
  2. 一個裝載使用說明文字的容器
  3. 一個裝載盒子列表的 section,每一個盒子包含輸入框

結構變得很簡單。

如下就是:

<main class="booth">
  <aside class="slider">
    <label>Move this 👇 </label>
    <input class="booth-slider" type="range" min="-50" max="50" value="-50" step="5"/>
  </aside>

  <section class="color-boxes">
    <div class="color-box" id="1"><input value="red"/></div>
    <div class="color-box" id="2"><input/></div>
    <div class="color-box" id="3"><input/></div>
    <div class="color-box" id="4"><input/></div>
    <div class="color-box" id="5"><input/></div>
    <div class="color-box" id="6"><input/></div>
  </section>

  <footer class="instructions">
    👉🏻 Move the slider<br/>
    👉🏻 Write any color in the red boxes
  </footer>
</main>
複製代碼

如下幾件事須要注意。

  1. 範圍輸入表明了從 -5050 範圍的值,step 值爲 5。所以範圍輸入的最小值就是 -50
  2. 若是你並不肯定範圍輸入是否能夠運行,能夠在 w3schools 上檢查如下
  3. 注意類名爲 .color-boxes 的 section 是如何包含其它 .color-box 容器的。這些容器中包含輸入框。
  4. 第一個輸入框有默認值爲 red。

理解了文檔結構後,給它添加樣式:

  1. .slider.instructions 設置爲脫離文檔流,將它們的 position 設置爲 absolute
  2. body 元素的背景色設置爲日出的顏色,並在左下角用花朵做裝飾
  3. color-boxes 容器定位到中間
  4. 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;
}
複製代碼

這段代碼並不像你想的那般複雜。但願你能通讀一遍並能讀懂,若是沒有的話,能夠留下評論或者發個 twitter。

body 添加樣式會涉及到更多內容,但願你足夠了解 CSS。

既然咱們想用背景顏色和背景圖來設置元素的樣式,那麼使用 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 position 屬性是如何工做的:

來自於: CSS 進階指南

來自於: CSS 進階指南

正斜槓後面的表明 background-size 被設置爲 340px,若是將它設置得更小的話,圖片也會變得更小。

no-repeat,你可能已經猜到它是作什麼的。它避免背景圖片自我複製,鋪滿背景。

最後,跟在逗號後面的是第二個背景屬性聲明。這一次,咱們僅僅將 background-color 設置爲 var(primary-color)

哇,這是個變量。

這意味着你必須定義變量。 就是這樣:

:root {
  --primary-color: rgba(241,196,15 ,1)
}
複製代碼

這裏講主題色設置爲日出黃。沒什麼大問題。立刻,咱們就會在這裏設置更多的變量。

如今,咱們將 color-boxes 定位到中間

main.booth {
  min-height: 100vh;

  display: flex;
  justify-content: center;
  align-items: center;
}
複製代碼

主容器充當 flex 容器,它的子元素會正確地被定位到頁面中間。也就是說咱們的 color-box 容器會被定位到頁面中間。

咱們把 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);
}
複製代碼

這就加上了好看的陰影,使得效果更酷炫了。

還沒結束,咱們給總體的 container-boxes 容器加上樣式:

/* 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;
}
複製代碼

你知道效果會變成什麼樣,對吧?

這裏有個新變量,須要在根元素中聲明添加進來。

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

第二個顏色是紅色,咱們會給容器加上紅色的背景。

接下來這部分可能會讓你以爲難以理解:

/* Color Boxes */
.color-boxes {
  transform: perspective(500px) rotateY( calc(var(--slider) * 1deg));
  transition: transform 0.3s
}
複製代碼

又是咱們會將 transform 的屬性值簡寫成上面這樣。

舉個例子:

transform: perspective(500px) rotateY( 30deg);
複製代碼

這個 transform 簡寫用了兩個不一樣的函數。一個是視角,另外一個是沿着 Y 軸旋轉。

那麼 perspective 函數 和 rotateY 函數是作什麼的呢?

perspective() 函數應用於 3D 空間內旋轉的元素。它激活了三維空間,並沿 z 軸給出元素的深度。

能夠在 codrops 上閱讀更多有關 perspective 的知識。

rotateY 函數是幹什麼的?

激活三維空間後,元素具備了 x,y,z 軸。rotateY 就是元素圍繞 Y 平面旋轉。

下面這個 codrops 的圖對於視覺化理解頗有幫助。

Codrops

我但願這能讓你更明白一些。

回到以前的話題。

當你回到這裏,你知道哪一個函數影響 .container-box 的旋轉了嗎?

是 rotateY 函數使得盒子沿着 Y 周旋轉。

因爲傳入 rotateY 函數的值將被 JavaScript 更新,這個值也將經過變量來傳入。

爲何要給變量乘上 1deg?

做爲通常的經驗法則,爲了顯式地更靈活,建議在構建單獨符號時變量中儲存沒有單位的值。

經過 calc 函數,你能夠用乘法將它們轉化成任何單位。

這意味着你能夠隨心所欲。將做爲比例的 deg 轉換爲視窗單位 vw 也能夠。

在這個場景中,咱們經過 「數字」 乘上 1deg 將數字轉換成角度

因爲 CSS 不懂數學,你須要將公式傳入 calc 函數,這樣 CSS 才能正確計算。

完成以後咱們就能夠繼續了。咱們能夠在 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 選擇器用來選擇子盒子。

這裏須要一些前瞻。咱們知道,每一個盒子的背景色都會更新。咱們也知道背景色須要用變量表示,以在 JavaScript 中更新。對吧?

接下來:

.color-box:nth-child(1) {
  background: var(--bg-1)
}
複製代碼

簡單吧。

這裏有個問題。若是變量不存在的話怎麼辦?

咱們一個回退方式。

這是可行的:

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

在這個特殊實例中,我選擇不提供任何回退方式。

若是某個屬性值中使用的變量非法,屬性將使用其初始值。

所以,當 --bg-1 非法或者不可用時,背景色會默認切換成它的初始顏色或者透明。

初始值指向屬性還未顯式設置時的值。好比說,若是你沒有給元素設置 background-color 屬性的話,它的背景色會默認爲 transparent

初始值是一種默認屬性值。

寫點 JavaScript

在 JavaScript 這一邊須要作的事情不多。

首先要處理一下 slider。

僅僅五行代碼就能夠!

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

// 一旦 slider 的範圍值發生變化,就執行回調
range.addEventListener('input', handleSlider)

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

這很簡單,對吧?

我來解釋一下。

首先,保存一份 slider 元素的引用,const range = document.querySelector('.booth-slider')

設置一個事件監聽器,一旦範圍輸入值發生變化就會觸發,range.addEventListener('input', handleSlider)

寫一個回調函數, handleSlider

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

root.style.setProperty('--slider', value) 的意思是獲取 root 元素(HTML),讀取它的樣式,並給它設置屬性。

處理顏色變化

這與處理 slider 值的變化同樣簡單。

這麼作就能夠:

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')

給每一個輸入框加上事件監聽:

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 變量的(又名自定義屬性)瀏覽器支持並不差。 瀏覽器支持性很是好,基本全部的現代瀏覽器都支持良好(本文寫做時已超過 87%)。

caniuse

那麼,你能夠在生產環境使用 CSS 變量嗎?固然能夠!可是這多大程度上適用於你還需本身判斷。

好的一面是,你可使用像 Myth 這樣的預處理器來使用 CSS 變量。它將「將來的」 CSS 預編譯成如今你就可使用的代碼,是否是很贊?

若是你有使用 postCSS 的經驗, 這也一樣是一個好方法。這是 postCSS 的 CSS 變量模塊

就這些,我已所有寫完。

很差,我遇到了問題!

購買電子書 能夠線上閱讀, 還能得到 私人的 slack 邀請,你能夠向我諮詢任何問題。

這是個公平交易,對吧?

稍後聯繫! 💕


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索