CSS 料理室 – CSS 變數辛香料:不用 Sass、不用 JavaScript,也能實做 Dark Mode Theme 切換!
02/26/2022 ・ Tech👩🍳 關於 CSS 料理室 :
CSS 料理室的主廚可能會打翻麵粉、可能會調配出黑暗料理,但是實驗精神是不會少的!
總之,讓我們一起透過一道又一道料理,認識 CSS 吧!
🍽 食譜完成照:
🥬 食材準備:
- CSS 變數:
-*
- HTML
input
標籤:input[type="checkbox"]
- CSS 選取器:
X + Y
,X ~ Y
📒 食譜簡介:
這次製作的料理,主要是使用原生的 CSS 變數 實做出深色模式和淺色模式的切換。除此之外,我們還會利用 HTML <input>
標籤當中的 checkbox
實做 『切換』這個動作,以下將介紹這些食材的特性。
🍖 食材介紹(ㄧ): CSS 自訂變數 (--*)
CSS 變數 (--*)
讓我們自訂命名,讓規範或常用的數值取一個名字,好讓其他成員在使用時可以更好理解。 例如:
/* 原本的樣式 */
.card {
background: #FFFFFF;
color: rgba(255, 98, 98, 1);
}
/* 使用自訂變數 */
:root {
--bg-white: #FFFFFF;
--text-pink: #FF6262;
}
/* 套上變數 */
.card {
background: var(--bg-white);
color: var(--text-pink);
}
從上面使用自訂變數的範例中,可以很快速的知道 .card
使用了 白色
的背景, 粉紅色的文字
樣式。
如果我們想要改粉紅色的色票,只要到 --text-pink
中去調整就行了!
全域 CSS 變數與獨立區域的 CSS 變數
在使用 CSS 變數時,也可以將這個變數選擇放在全域或是某個區域範圍內,在 :root {....}
當中的變數是全域共用的:
/* :root 全域共用的樣式 */
:root {
--pink: #FF6262;
}
/* 只有在 .container 裡面的 --pink */
.container {
--pink: #FF006B;
}
.container {
color: var(--pink); /* pink => #FF006B */
}
body {
color: var(--pink); /* pink => #FF6262 */
}
🍖 食材介紹(二): <input type="checkbox">
<input type="checkbox">
是一個單純的勾選標籤,有三種狀態:
並且在 CSS 也可以直接設定這些狀態樣式,例如:
input[type="checkbox"] {
/* Unchecked 的樣式 */
}
input[type="checkbox"]:checked {
/* checked 的樣式 */
}
input[type="checkbox"]:indeterminate {
/* indeterminate 的樣式 */
}
其中 indeterminate
這個介於已選取和未選取之間的狀態,是需要透過 JavaScript 去定義在什麼情況下會出現 indeterminate
狀態。這次不會使用這個狀態。
我們可以利用 checkbox 的兩個狀態 : unchecked
& checked
去做到類似 JavaScript『點擊』後觸發的樣式。
🍖 食材介紹(三): CSS 選取器 X + Y
, X ~ Y
最後一個重要食材 – CSS 選取器,從上面兩個食材當中我們已經準備好:
- 將樣式顏色命名:管理 CSS 自訂變數
- 如何觸發樣式:使用
<input type=checkbox>
接著,我們需要指定樣式『套用的範圍』。 從完成照當中仔細地看到,我是將滑鼠進入 Dark / Light 的按鈕時才會觸發,實際上 HTML 的結構層,我是將卡片和按鈕排在同一層,讓觸發範圍限制在按鈕樣式 <input>
裡。如果我將卡片樣式放進去 <input>
裡,那麼整張卡片將會一起被當成觸發範圍。
如果我的 input 和卡片樣式是同層的話,我可以透過 X ~ Y
來選取:
CSS 選取器: X ~ Y
選取同層(兄弟層)的元素,意思是選取在 X
之後的 Y
。
CSS 選取器:X + Y
選取緊鄰的同層元素,參考以下範例,他只會選取到緊鄰<h1>
的 <p>
。
👩🍳 料理步驟: 實現 CSS 變數 Dark Mode 吧!
🖋 步驟一:使用 CSS 自訂變數,建立色票
首先,先將深色和淺色模式會使用到的顏色都先運用自訂變數,建立色票,準備好:
:root {
--bg-color: #F1E8E8;
--white: #FFFFFF;
--black: #282F3C;
--pink: rgba(255, 98, 98, 1);
--pink-light: rgba(255, 98, 98, 0.3);
--pink-lighter: rgba(255, 98, 98, 0.1);
--gray: #959595;
}
🖋 步驟二:設定 Checkbox 樣式
<div class="container">
<input type="check" type="checkbox" id="toggle" name="toggletheme">
<label for="toggle">
<span class="dark">Dark</span>
<span class="light">Light</span>
</label>
</input>
</div>
1. <label>
標籤的 for
屬性:
在示範上將 <label>
存取文字,並且放在與 <input>
同層的位置,我們可以指定這兩者產生關聯,讓 <input>
觸發的條件對應到 <label>
內。如何設置呢? 將 <input>
的 id
與 <label>
的 for
設置成相同值:
2. 選取 <input>
緊鄰的 <label>
首先我們將瀏覽預設的 <input>
樣式隱藏,並透過 <label>
建立這個按鈕的樣式。
我使用 X + Y
從 <input>
狀態控制 <label>
樣式,實際上操作會像這樣:
/* 隱藏預設 input 樣式 */
input[type="checkbox"] {
display: none;
}
/* input[type="checkbox"] 緊鄰的 label */
/* 在 checkbox 未點擊的樣式 */
input[type="checkbox"] + label {
......
}
/* 在 checkbox 點擊後的樣式 */
input[type="checkbox"]:checked + label {
.....
}
Tip: 可以看到 label
裡面有 <span>Dark</span>
和 <span>Light</span>
這會用 checked
判斷在 Light 模式時,<span>Light</span>
的文字隱藏,Dark 模式則是相反。
3. ::before
圓形樣式:
另外使用 ::before
做出假圓形,模擬出按鈕樣式:
從上面的 Toggle 按鈕當中可以看到,我已經選取到 :checked
的狀態時,按鈕會是如何呈現的,如此就能夠延伸出在 :checked
狀態下的 .card
的樣式。
🖋 步驟三:刻出卡片
從上一步,我們建立了切換深淺色的按鈕後,接著我們就可以利用:
使用 CSS 選取器 X ~ Y
製作卡片樣式。
首先 input
、 label
和製作卡片的樣式 <div class="card"></div>
放在同層,像以下:
<div class="container">
<!-- 按鈕 -->
<input type="checkbox" id="toggle" name="toggletheme"></input>
<label for="toggle"></label>
<!-- 卡片樣式 -->
<div class="card">
......
</div>
</div>
可以從上面看到,要使用 <input>
的 :checked
選取器來製作點擊後的卡片樣式,中間隔了 <label>
要怎麼樣能夠跨過 <label>
呢?
這時候就可以使用 CSS 選取器:X ~ Y
! 直接選取在 <input>
之後的 <div class="card">
因此我們就能夠這樣做設定:
/* 預設卡片樣式 (未點擊的狀態) */
.card {
...
}
/* 點擊後的卡片樣式 (Dark Mode) */
input[type="checkbox"]:checked ~ .card {
...
}
🎁 Bonus – CSS 選取器:X > Y
從完成的 Card
樣式,可以看到我使用大量的 X > Y
方式選取,這個選取器的特性是什麼呢?
X > Y
是選取緊鄰的子層元素,這邊則是選取相連同層的元素,讓我們看以下範例:
結語
以上就是這次的 CSS 料理室 – CSS 變數辛香料,看完你是否也想嘗試玩玩看 Dark Mode 切換了嗎?
雖然對於 CSS 變數命名還是覺得有點長(囉唆?XD )
但,看到 CSS 解決了變數的方法,真覺得是一大福音啊!
除此之外 CSS 的 :checked
也是一個很有趣的的選取器,實務上也經常使用這樣的選取器製作像是收合樣式、開啟關閉的樣式,
更多的方法也可以參閱:You Don’t Need JavaScript | Accordion