通過 CSS自定義屬性(CSS變數)和 JavaScript 實現高階CSS主題切換

在本教程中,我們將使用 CSS自定義屬性(也稱為CSS變數)來為簡單的HTML頁面實現主題切換。 我們將建立暗黑和明亮的示例主題,然後編寫JavaScript 以在使用者單擊按鈕時在兩者之間切換。
如果你以前沒接觸過,請先閱讀 ofollow,noindex" target="_blank">CSS變數(自定義屬性)實用指南及注意事項 這篇文章
就像在典型的程式語言中一樣,變數用於儲存或儲存值。 在CSS中,它們通常用於儲存顏色,字型名稱,字型大小,長度單位等。然後可以在樣式表中的多個位置引用和重用它們。 大多數開發人員都會引用 “CSS變數” ,但官方名稱是 自定義屬性 。
CSS自定義屬性可以修改可在整個樣式表中引用的變數。 以前,只有使用Sass等CSS前處理器才能實現這一點。
理解 :root 和 var()
在建立動態主題示例之前,讓我們瞭解自定義屬性的基本基礎知識。
自定義屬性 是一個名稱以兩個連字元( -
)開頭的屬性,如 --foo
。 定義後可以使用 var()
引用的變數。 讓我們考慮這個例子:
:root { --bg-color: #000; --text-color: #fff; }
在 :root
選擇器中定義自定義屬性意味著它們可以作用於全域性文件中所有元素。 :root
是一個CSS偽類,它匹配文件的根元素 – <html>
元素。它類似於 html
選擇器,但具有更高的 優先順序 。
您可以在文件中的任何位置訪問 :root
中的自定義屬性的值:
div { color: var(--text-color); background-color: var(--bg-color); }
您還可以在CSS變數中包含回退值。例如:
div { color: var(--text-color, #000); background-color: var(--bg-color, #fff); }
如果未定義自定義屬性,則使用其回退值代替。
除了 :root
或 html
選擇器之外的CSS選擇器內定義的自定義屬性使變數可用於匹配元素及其子元素。
CSS自定義屬性與前處理器變數
諸如 Sass 之類的CSS前處理器通常用於輔助前端Web開發。前處理器的其中一個有用功能就包括變數。但是Sass變數和CSS自定義屬性之間有什麼區別?
- CSS自定義屬性在現代瀏覽器中進行本機解析。 前處理器變數需要編譯到標準CSS檔案中,並且所有變數都轉換為值。
- JavaScript可以訪問和修改自定義屬性。 預處理程式變數編譯一次,只有它們的最終值在客戶端上可用。
編寫一個簡單的HTML頁面
讓我們從為專案建立一個資料夾開始:
$ mkdir css-variables-theming
接下來,在專案的資料夾中新增一個 index.html
檔案:
$ cd css-variables-theming $ touch index.html
並新增以下內容:
<nav class="navbar">Title</nav> <div class="container"> <div> <input type="button" value="Light/Dark" id="toggle-theme" /> </div> <h2 class="title">What is Lorem Ipsum?</h2> <p class="content">Lorem Ipsum is simply dummy text of the printing and typesetting industry...</p> </div> <footer> Copyright 2018 </footer>
我們使用 <nav>
標籤新增一個導航欄,頁尾和容器 <div>
,容器中包含一個按鈕(用於在明暗主題之間切換)和一些虛擬 Lorem Ipsum 文字。
為我們的HTML頁面編寫基本CSS
現在讓我們為頁面新增樣式。在 <head>
中使用內聯 <style>
標記的同一檔案中新增以下CSS樣式:
<style> * { margin: 0; } html{ height: 100%; } body{ height: 100%; font-family: -apple-system, BlinkMacSystemFont“Segoe UI”, “Roboto”, “Oxygen”, “Ubuntu”, “Cantarell”, “Fira Sans”, “Droid Sans”, “Helvetica Neue”,sans-serif; display: flex; flex-direction: column; } nav{ background: hsl(350, 50%, 50%); padding: 1.3rem; color: hsl(350, 50%, 10%); } .container{ flex: 1; background:hsl(350, 50%, 95%); padding: 1rem; } p.content{ padding: 0.7rem; font-size: 0.7rem; color: hsl(350, 50%, 50%); } .container h2.title{ padding: 1rem; color: hsl(350, 50%, 20%); } footer{ background: hsl(350, 93%, 88%); padding: 1rem; } input[type=button] { color:hsl(350, 50%, 20%); padding: 0.3rem; font-size: 1rem; } </style>
CSS3 HSL(色調,飽和度,亮度)表示法用於定義顏色。 色調是色環上的角度,示例使用350表示紅色。 通過更改飽和度(顏色百分比)和亮度(百分比),所有頁面顏色都使用不同的變化。
使用HSL,我們只需更改色調值,即可輕鬆嘗試主題的不同主色。 我們還可以使用CSS變數作為色調值,並通過更改樣式表中的單個值或使用JavaScript動態更改顏色主題來切換顏色主題。
這是頁面的螢幕截圖:
我們將這個例子放到線上的 CodePen 中演示:
See the Pen CSS Theming 1 by feiwen8772 ( @feiwen8772 ) on CodePen .0
讓我們使用CSS變數來儲存頁面中所有顏色的色調值。在 <style>
標記頂部的 :root
選擇器中新增一個全域性CSS變數:
:root{ --main-hue : 350; }
接下來,我們用 -main-hue
變數替換 hsl()
顏色中的所有硬編碼350值。例如,這是導航選擇器:
nav{ background: hsl(var(--main-hue) , 50%, 50%); padding: 1.3rem; color: hsl(var(--main-hue), 50%, 10%); }
現在,如果要指定除紅色以外的其他顏色,則只需將相應的值指定給 --main-hue
即可。這裡有一些例子:
:root{ --red-hue: 360; --blue-hue: 240; --green-hue: 120; --main-hue : var(--red-hue); }
我們為紅色,藍色和綠色定義了三個自定義屬性,然後將 --red-hue
變數分配給 --main-hue
。
這是一個螢幕截圖,其中包含不同值的頁面 --main-hue
:
CSS自定義屬性提供了幾個好處:
--main-hue
使用JavaScript從一組預定義值或使用者提交的hue值(它應該在0到360之間)動態設定 --main-hue
的值,我們可以為使用者提供許多彩色主題的可能性。
以下程式碼行將 --main-hue
的值設定為240(藍色):
document.documentElement.style.setProperty('--main-hue', 240);
檢視以下 CodePen ,其顯示了一個完整示例,允許您在紅色,藍色和綠色之間動態切換主題:
See the Pen CSS Theming 2 by feiwen8772 ( @feiwen8772 ) on CodePen .0
他是頁面的截圖:
新增CSS暗黑主題
現在讓我們為這個頁面提供一個暗黑的主題。 為了更好地控制不同實體的顏色,我們需要新增更多變數。
通過頁面的樣式,我們可以在 :root
中定義對應顏色的自定義屬性後,用變數替換不同選擇器中的所有HSL顏色:
:root{ /*...*/ --nav-bg-color: hsl(var(--main-hue) , 50%, 50%); --nav-text-color: hsl(var(--main-hue), 50%, 10%); --container-bg-color: hsl(var(--main-hue) , 50%, 95%); --content-text-color: hsl(var(--main-hue) , 50%, 50%); --title-color: hsl(var(--main-hue) , 50%, 20%); --footer-bg-color: hsl(var(--main-hue) , 93%, 88%); --button-text-color: hsl(var(--main-hue), 50%, 20%); }
使用了自定義屬性的適當名稱。 例如, --nav-bg-color
是指導航背景的顏色,而 --nav-text-color
是指導航前景/文字的顏色。
現在複製 :root
選擇器及其內容,但新增一個暗黑屬性值的主題:
:root[theme='dark']{ /*...*/ }
如果將具有 dark
值的 theme
屬性新增到 <html>
元素,則會啟用此主題。
我們現在可以手動插入這些變數的值,通過減少 HSL 顏色的亮度值來提供暗主題,或者我們可以使用其他技術,例如常用的 invert()
和 brightness()
等CSS濾鏡調整影象的渲染,但也可以與任何其他元素一起使用。
將以下程式碼新增到 :root[theme='dark']
:
:root[theme='dark'] { --red-hue: 360; --blue-hue: 240; --green-hue: 120; --main-hue: var(--blue-hue); --nav-bg-color: hsl(var(--main-hue), 50%, 90%); --nav-text-color: hsl(var(--main-hue), 50%, 10%); --container-bg-color: hsl(var(--main-hue), 50%, 95%); --content-text-color: hsl(var(--main-hue), 50%, 50%); --title-color: hsl(--main-hue, 50%, 20%); --footer-bg-color: hsl(var(--main-hue), 93%, 88%); --button-text-color: hsl(var(--main-hue), 50%, 20%); filter: invert(1) brightness(0.6); }
invert()
過濾器反轉所選元素中的所有顏色(在這種情況下每個元素都會應用)。 可以用百分比或數字指定反轉值。 值 100%
或 1
將完全反轉元素的色調,飽和度和亮度值。
brightness()
濾鏡使元素更亮或更暗。 值為 0
會導致完全黑色的元素。
invert()
濾鏡使一些元素非常明亮。 通過設定 brightness(0.6)
來降低這些要求。
暗黑主題,不同程度的色調:
使用JavaScript切換主題
現在,當用戶點選 Dark / Light 按鈕時,我們現在使用JavaScript在暗黑和高亮主題之間切換。 在 index.html
中,使用以下程式碼在結束 </body>
之前新增內聯 <script>
:
const toggleBtn = document.querySelector("#toggle-theme"); toggleBtn.addEventListener('click', e => { console.log("Switching theme"); if(document.documentElement.hasAttribute('theme')){ document.documentElement.removeAttribute('theme'); } else{ document.documentElement.setAttribute('theme', 'dark'); } });
document.documentElement
引用文件的根DOM元素 – 即 <html>
元素。 此程式碼使用 .hasAttribute()
方法檢查 theme
屬性是否存在,如果該屬性不存在則新增 dark
值,從而導致切換到暗黑主題。 否則,它會刪除該屬性,從而切換到高亮主題。
使用JavaScript更改CSS自定義屬性
使用JavaScript,我們可以訪問自定義屬性並動態更改其值。 在我們的示例中,我們對亮度值進行了硬編碼,但它可以動態更改。 首先,在 Dark / Light 按鈕旁邊的 HTML 頁面中新增 slider input:
<input type="range" id="darknessSlider" name="darkness" value="1" min="0.3" max="1" step="0.1" />
slider 從 1
開始,允許使用者將其減小到 0.3
,步長為 0.1
。
接下來,在 :root[theme='dark']
中為暗度值新增一個自定義屬性,初始值為 1
:
:root[theme='dark']{ /*...*/ --theme-darkness: 1; }
將 brightness
濾鏡更改為此自定義屬性而不是硬編碼值:
filter: invert(1) brightness(var(--theme-darkness));
最後,新增以下程式碼以將 --theme-darkness
的值與 slider 值同步:
const darknessSlider = document.querySelector("#darknessSlider"); darknessSlider.addEventListener('change', (e)=>{ const val = darknessSlider.value document.documentElement.style.setProperty('--theme-darkness', val); });
我們正在監聽滑塊的 change
事件,並使用 setProperty()
方法相應地設定 --theme-darkness
的值。
我們還可以將 brightness
濾鏡應用於高亮主題。 在 :root
選擇器的頂部新增 --theme-darkness
自定義屬性:
:root{ /*...*/ --theme-darkness: 1; }
然後在同一選擇器的底部新增 brightness
濾鏡:
:root{ /*...*/ filter: brightness(var(--theme-darkness)); }
您可以在以下線上的 CodePen 中演示中找到此示例的完整程式碼:
See the Pen CSS Theming by feiwen8772 ( @feiwen8772 ) on CodePen .0
這是最後一個例子的暗黑主題的截圖:
這個是高亮主題的截圖:
結論
在本教程中,我們已經瞭解瞭如何使用CSS自定義屬性來建立主題並在它們之間動態切換。 我們使用了HSL配色方案,它允許我們指定具有色調,飽和度和亮度值的顏色以及CSS濾鏡( invert
和 brightness
)以建立淺色主題的暗色版本。
如果您想了解有關CSS主題的更多資訊,請參閱以下連結進一步閱讀:
- Using CSS custom properties (variables)
- HSL and HSV
- CSS Custom Properties and Theming
- Dark theme in a day
原文連結: https://www.sitepoint.com/css-theming-custom-properties-javascript/