在本教程中杆麸,我們將使用 CSS自定義屬性(也稱為CSS變量)來(lái)為簡(jiǎn)單的HTML頁(yè)面實(shí)現(xiàn)主題切換。 我們將創(chuàng)建暗黑和明亮的示例主題浪感,然后編寫JavaScript 以在用戶單擊按鈕時(shí)在兩者之間切換昔头。
就像在典型的編程語(yǔ)言中一樣,變量用于保存或存儲(chǔ)值影兽。 在CSS中揭斧,它們通常用于存儲(chǔ)顏色,字體名稱峻堰,字體大小讹开,長(zhǎng)度單位等。然后可以在樣式表中的多個(gè)位置引用和重用它們茧妒。 大多數(shù)開(kāi)發(fā)人員都會(huì)引用 “CSS變量” 萧吠,但官方名稱是 自定義屬性。
CSS自定義屬性可以修改可在整個(gè)樣式表中引用的變量。 以前贷腕,只有使用Sass等CSS預(yù)處理器才能實(shí)現(xiàn)這一點(diǎn)邻遏。
理解 :root 和 var()
在創(chuàng)建動(dòng)態(tài)主題示例之前怠褐,讓我們了解自定義屬性的基本基礎(chǔ)知識(shí)圃酵。
自定義屬性 是一個(gè)名稱以兩個(gè)連字符( - )開(kāi)頭的屬性悦施,如 --foo虐呻。 定義后可以使用 var() 引用的變量牧氮。 讓我們考慮這個(gè)例子:
CSS 代碼:
:root {? --bg-color: #000;? --text-color: #fff;}
在:root選擇器中定義自定義屬性意味著它們可以作用于全局文檔中所有元素琼腔。:root是一個(gè)CSS偽類,它匹配文檔的根元素 – <html>元素踱葛。它類似于 html 選擇器丹莲,但具有更高的優(yōu)先級(jí)。
您可以在文檔中的任何位置訪問(wèn) :root 中的自定義屬性的值:
CSS 代碼:
div {? color: var(--text-color);? background-color: var(--bg-color);}
您還可以在CSS變量中包含回退值尸诽。例如:
CSS 代碼:
div {? color: var(--text-color, #000);? background-color: var(--bg-color, #fff);}
如果未定義自定義屬性甥材,則使用其回退值代替。
除了?:root?或?html?選擇器之外的CSS選擇器內(nèi)定義的自定義屬性使變量可用于匹配元素及其子元素性含。
CSS自定義屬性與預(yù)處理器變量
諸如 Sass 之類的CSS預(yù)處理器通常用于輔助前端Web開(kāi)發(fā)洲赵。預(yù)處理器的其中一個(gè)有用功能就包括變量。但是Sass變量和CSS自定義屬性之間有什么區(qū)別商蕴?
CSS自定義屬性在現(xiàn)代瀏覽器中進(jìn)行本機(jī)解析叠萍。 預(yù)處理器變量需要編譯到標(biāo)準(zhǔn)CSS文件中,并且所有變量都轉(zhuǎn)換為值绪商。
JavaScript可以訪問(wèn)和修改自定義屬性苛谷。 預(yù)處理程序變量編譯一次,只有它們的最終值在客戶端上可用格郁。
編寫一個(gè)簡(jiǎn)單的HTML頁(yè)面
讓我們從為項(xiàng)目創(chuàng)建一個(gè)文件夾開(kāi)始:
BASH 代碼:
$ mkdir css-variables-theming
接下來(lái)抄腔,在項(xiàng)目的文件夾中添加一個(gè)?index.html?文件:
BASH 代碼:
$ cd css-variables-theming$ touch index.html
并添加以下內(nèi)容:
HTML 代碼:
Title
What is Lorem Ipsum?
? ?Lorem Ipsum is simply dummy text of the printing and typesetting industry...
我們使用?<nav>?標(biāo)簽添加一個(gè)導(dǎo)航欄,頁(yè)腳和容器?<div>?理张,容器中包含一個(gè)按鈕(用于在明暗主題之間切換)和一些虛擬?Lorem Ipsum?文本赫蛇。
為我們的HTML頁(yè)面編寫基本CSS
現(xiàn)在讓我們?yōu)轫?yè)面添加樣式。在?<head>?中使用內(nèi)聯(lián)?<style>?標(biāo)記的同一文件中添加以下CSS樣式:
HTML 代碼:
* {? 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;}
CSS3 HSL(色調(diào)雾叭,飽和度悟耘,亮度)表示法用于定義顏色。 色調(diào)是色環(huán)上的角度织狐,示例使用350表示紅色暂幼。 通過(guò)更改飽和度(顏色百分比)和亮度(百分比),所有頁(yè)面顏色都使用不同的變化移迫。
使用HSL旺嬉,我們只需更改色調(diào)值,即可輕松嘗試主題的不同主色厨埋。 我們還可以使用CSS變量作為色調(diào)值邪媳,并通過(guò)更改樣式表中的單個(gè)值或使用JavaScript動(dòng)態(tài)更改顏色主題來(lái)切換顏色主題。
這是頁(yè)面的屏幕截圖:
我們將這個(gè)例子放到在線的 CodePen 中演示:
讓我們使用CSS變量來(lái)保存頁(yè)面中所有顏色的色調(diào)值。在 <style> 標(biāo)記頂部的 :root 選擇器中添加一個(gè)全局CSS變量:
CSS 代碼:
:root{? --main-hue : 350;}
接下來(lái)雨效,我們用 -main-hue 變量替換 hsl() 顏色中的所有硬編碼350值迅涮。例如,這是導(dǎo)航選擇器:
CSS 代碼:
nav{? background: hsl(var(--main-hue) , 50%, 50%);? padding: 1.3rem;? color: hsl(var(--main-hue), 50%, 10%);}
現(xiàn)在徽龟,如果要指定除紅色以外的其他顏色叮姑,則只需將相應(yīng)的值指定給 --main-hue 即可。這里有一些例子:
CSS 代碼:
:root{? --red-hue: 360;? --blue-hue: 240;? --green-hue: 120;? --main-hue : var(--red-hue);}
我們?yōu)榧t色据悔,藍(lán)色和綠色定義了三個(gè)自定義屬性传透,然后將 --red-hue 變量分配給--main-hue。
這是一個(gè)屏幕截圖极颓,其中包含不同值的頁(yè)面 --main-hue :
CSS自定義屬性提供了幾個(gè)好處:
可以在單獨(dú)位置定義值旷祸。
可以適當(dāng)?shù)孛撝狄詭椭S護(hù)和可讀性。
可以使用JavaScript動(dòng)態(tài)更改該值讼昆。 例如托享,--main-hue 可以設(shè)置為0到360之間的任何值。
使用JavaScript從一組預(yù)定義值或用戶提交的hue值(它應(yīng)該在0到360之間)動(dòng)態(tài)設(shè)置 --main-hue 的值浸赫,我們可以為用戶提供許多彩色主題的可能性闰围。
以下代碼行將 --main-hue 的值設(shè)置為240(藍(lán)色):
JavaScript 代碼:
document.documentElement.style.setProperty('--main-hue', 240);
查看以下 CodePen ,其顯示了一個(gè)完整示例既峡,允許您在紅色羡榴,藍(lán)色和綠色之間動(dòng)態(tài)切換主題:
他是頁(yè)面的截圖:
添加CSS暗黑主題
現(xiàn)在讓我們?yōu)檫@個(gè)頁(yè)面提供一個(gè)暗黑的主題。 為了更好地控制不同實(shí)體的顏色运敢,我們需要添加更多變量校仑。
通過(guò)頁(yè)面的樣式,我們可以在:root中定義對(duì)應(yīng)顏色的自定義屬性后传惠,用變量替換不同選擇器中的所有HSL顏色:
CSS 代碼:
: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%);}
使用了自定義屬性的適當(dāng)名稱迄沫。 例如, --nav-bg-color 是指導(dǎo)航背景的顏色卦方,而 --nav-text-color 是指導(dǎo)航前景/文本的顏色羊瘩。
現(xiàn)在復(fù)制 :root 選擇器及其內(nèi)容,但添加一個(gè)暗黑屬性值的主題:
CSS 代碼:
:root[theme='dark']{? /*...*/}
如果將具有dark值的 theme 屬性添加到 <html> 元素盼砍,則會(huì)激活此主題尘吗。
我們現(xiàn)在可以手動(dòng)插入這些變量的值,通過(guò)減少 HSL 顏色的亮度值來(lái)提供暗主題浇坐,或者我們可以使用其他技術(shù)睬捶,例如常用的 invert() 和 brightness() 等CSS濾鏡調(diào)整圖像的渲染,但也可以與任何其他元素一起使用近刘。
將以下代碼添加到 :root[theme='dark']:
CSS 代碼:
: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() 過(guò)濾器反轉(zhuǎn)所選元素中的所有顏色(在這種情況下每個(gè)元素都會(huì)應(yīng)用)擒贸。 可以用百分比或數(shù)字指定反轉(zhuǎn)值臀晃。 值 100% 或 1 將完全反轉(zhuǎn)元素的色調(diào),飽和度和亮度值酗宋。
brightness() 濾鏡使元素更亮或更暗积仗。 值為 0 會(huì)導(dǎo)致完全黑色的元素疆拘。
invert() 濾鏡使一些元素非常明亮蜕猫。 通過(guò)設(shè)置 brightness(0.6) 來(lái)降低這些要求。
暗黑主題哎迄,不同程度的色調(diào):
使用JavaScript切換主題
現(xiàn)在回右,當(dāng)用戶點(diǎn)擊 Dark / Light 按鈕時(shí),我們現(xiàn)在使用JavaScript在暗黑和高亮主題之間切換漱挚。 在 index.html 中翔烁,使用以下代碼在結(jié)束 </body> 之前添加內(nèi)聯(lián) <script> :
JavaScript 代碼:
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 值蹬屹,從而導(dǎo)致切換到暗黑主題。 否則白华,它會(huì)刪除該屬性慨默,從而切換到高亮主題。
使用JavaScript更改CSS自定義屬性
使用JavaScript弧腥,我們可以訪問(wèn)自定義屬性并動(dòng)態(tài)更改其值厦取。 在我們的示例中,我們對(duì)亮度值進(jìn)行了硬編碼管搪,但它可以動(dòng)態(tài)更改虾攻。 首先,在 Dark / Light 按鈕旁邊的 HTML 頁(yè)面中添加 slider input:
HTML 代碼:
slider 從?1?開(kāi)始更鲁,允許用戶將其減小到?0.3?霎箍,步長(zhǎng)為?0.1?。
接下來(lái)澡为,在:root[theme='dark']中為暗度值添加一個(gè)自定義屬性朋沮,初始值為1?:
CSS 代碼:
:root[theme='dark']{ /*...*/? --theme-darkness: 1;}
將?brightness?濾鏡更改為此自定義屬性而不是硬編碼值:
CSS 代碼:
filter: invert(1) brightness(var(--theme-darkness));
最后,添加以下代碼以將?--theme-darkness?的值與 slider 值同步:
JavaScript 代碼:
const darknessSlider = document.querySelector("#darknessSlider");darknessSlider.addEventListener('change', (e)=>{ const val = darknessSlider.value? document.documentElement.style.setProperty('--theme-darkness', val);});
我們正在監(jiān)聽(tīng)滑塊的?change?事件缀壤,并使用?setProperty()?方法相應(yīng)地設(shè)置?--theme-darkness?的值樊拓。
我們還可以將?brightness?濾鏡應(yīng)用于高亮主題。 在?:root?選擇器的頂部添加?--theme-darkness?自定義屬性:
CSS 代碼:
:root{ /*...*/? --theme-darkness: 1;}
然后在同一選擇器的底部添加?brightness?濾鏡:
CSS 代碼:
:root{ /*...*/? filter: brightness(var(--theme-darkness));}
您可以在以下在線的 CodePen 中演示中找到此示例的完整代碼:
這是最后一個(gè)例子的暗黑主題的截圖:
這個(gè)是高亮主題的截圖:
結(jié)論
在本教程中塘慕,我們已經(jīng)了解了如何使用CSS自定義屬性來(lái)創(chuàng)建主題并在它們之間動(dòng)態(tài)切換筋夏。 我們使用了HSL配色方案,它允許我們指定具有色調(diào)图呢,飽和度和亮度值的顏色以及CSS濾鏡(invert 和brightness)以創(chuàng)建淺色主題的暗色版本条篷。
來(lái)源:https://www.sitepoint.com/css-theming-custom-properties-javascript/
如果您在web學(xué)習(xí)的過(guò)程中遇到難題骗随,歡迎關(guān)注微信公眾號(hào)【筑夢(mèng)前端】,大家一起交流解決赴叹!