CSS 料理室 (一) | CSS 變數辛香料:不用 Sass、不用 JavaScript,也能實做 Dark Mode Theme 切換!

#variables #CSS
Debby
技術文章
CSS 料理室 (一) | CSS 變數辛香料:不用 Sass、不用 JavaScript,也能實做 Dark Mode Theme 切換!


👩‍🍳 關於 CSS 料理室 :

CSS 料理室的主廚可能會打翻麵粉、可能會調配出黑暗料理,但是實驗精神是不會少的!

總之,讓我們一起透過一道又一道料理,認識 CSS 吧!

🍽 食譜完成照:

🥬 食材準備:

  1. CSS 變數: --*
  2. HTML input 標籤: input[type="checkbox"]
  3. 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 選取器,從上面兩個食材當中我們已經準備好:

  1. 將樣式顏色命名:管理 CSS 自訂變數
  2. 如何觸發樣式:使用 <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="checkbox" id="toggle" name="toggletheme">
  <label for="toggle">
    <span class="dark">Dark</span>
    <span class="light">Light</span>
  </label>
</div>
1. <label> 標籤的 for 屬性:

在示範上將 <label> 存取文字,並且放在與 <input> 同層的位置,我們可以指定這兩者產生關聯,讓 <input> 觸發的條件對應到 <label> 內。如何設置呢?
<input>id<label>for 設置成相同值:

更詳細的介紹:<label> - HTML | MDN

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 製作卡片樣式。

首先 inputlabel 和製作卡片的樣式 <div class="card"></div> 放在同層,像以下:

<div class="container">

  <!-- 按鈕 -->
  <input type="checkbox" id="toggle" name="toggletheme">
  <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

如果你有試做這次的料理 🥘 ,歡迎分享給我們知道!或是製作上有任何問題歡迎來信交流👋 ~ !


👩‍🏫 課務小幫手:

✨ 想掌握 HTML/CSS 的觀念和原理嗎?

我們有開設新手也能輕鬆掌握 HTML、CSS!前進網頁進階實戰唷 ❤️️