翻譯:瘋狂的技術宅
原文:https://www.creativebloq.com/how-to/how-to-implement-light-or-dark-modes-in-css
CSS 規(guī)范一直在不斷發(fā)展甘耿。盡管在 CSS 新功能的實現(xiàn)很復雜,但是 CSS 工作組還是決定要把簡化版作為新元素添加到規(guī)范中竿滨。然后由瀏覽器來實現(xiàn)這些新元素佳恬,瀏覽器自行決定以哪種順序去實現(xiàn)它們,這就是為什么現(xiàn)在對新功能的支持不匹配的原因于游。雖然這可能會令人討厭毁葱,但實際上完成了規(guī)范的瀏覽器要好得多。
CSS 工作組的成員來自主要瀏覽器供應商和 Apple 贰剥、Adobe等其他技術公司倾剿。 Apple 最近推出了新版的 MacOS,并希望能夠在瀏覽器中檢測到新加入的深色模式鸠澈。為了做到這一點柱告,Apple 推薦了一個新的 5 級媒體查詢規(guī)范。
@media (prefers-color-scheme: light | dark)
{ … }
使用這個媒體查詢笑陈,可以檢測用戶是否正在使用操作系統(tǒng)的淺色或深色模式际度。不過目前僅支持 Safari Technology Preview 69 及更高版本,但其他瀏覽器不應落在后面涵妥。
為了測試這個功能乖菱,你需要升級到 Mojave 10.14(MacOS)并在“系統(tǒng)偏好設置”中選擇“深色”。我們可以通過好幾種方式使用這種新的媒體查詢來實現(xiàn)不同的主題蓬网。在將在本教程中將會探討其中的一些內(nèi)容窒所。
01. 設置頁面
首先,我們需要有一些 HTML 元素來設置樣式帆锋,所以先到 CodePen 創(chuàng)建一個新文件并添加一些元素吵取。首先添加一個容器,以便將內(nèi)容集中起來锯厢,然后再添加一些標題和文本皮官。將 CSS 設置為使用 Sass 以便在CSS中使用嵌套。
<div class="content-container">
<h1>Heading One</h1>
<h2>Heading Two</h2>
<hr>
<p>…</p>
<p>…</p>
</div>
02. 基本元素的樣式
接下來將會添加一些基本樣式实辑,其中包含一些來自Google的字體捺氢,這樣可使的頁面看起來更好一些。我們要設置所有基本元素的樣式剪撬,并應用新的字體大小摄乒、顏色和字體。
body {
font-family: 'Merriweather', serif;
background-color: #ededed;
color: #212121;
padding: 1.618rem;
line-height: 1.618;
font-size: 16px;
}
03. 容器的樣式
為容器設置一個舒適的閱讀樣式
接下來,為容器設置樣式馍佑,把內(nèi)容的行調(diào)整為為閱讀時舒適的長度斋否。另外還會添加背景顏色和陰影。為了使頁面中的內(nèi)容框居中挤茄,在邊距屬性的左右值上使用關鍵字 “auto”如叼。
.content-container {
padding: 1.618rem 3.236rem;
max-width: 48.54rem;
margin: 3.236rem auto;
background-color: #fff;
box-shadow: 0 0 12px 6px rgba(0,0,0,0.05);
border-radius: .269666667rem;
}
04. 添加高亮顏色
選擇一種高亮顏色并生成樣式
大多數(shù)網(wǎng)站都會在文本中的某處使用其它顏色,但是目前我們只有白色和灰色穷劈,所以現(xiàn)在要選擇一種高亮顏色并用這種顏色的創(chuàng)建樣式笼恰。我們使用 span 標簽應用顏色,并用它來突出顯示文本中的內(nèi)容歇终。
<span class="text--alpha">Lorem ipsum</span>
.text--alpha {
color: #c3423f;
}
05. 實現(xiàn)媒體查詢
現(xiàn)在有了一些樣式社证,就可以實現(xiàn)媒體查詢了
現(xiàn)在我們有了一個包含一些基本樣式的頁面,接著實現(xiàn)媒體查詢的方法评凝。讓我們包括它并重寫一些樣式追葡。先從 body 開始。
@media (prefers-color-scheme: dark)
{
body {
background-color: #111;
}
}
06. 覆蓋其余樣式
現(xiàn)在你可以覆蓋其余的樣式
現(xiàn)在可以看到媒體查詢正在運行并且 body 的背景顏色已經(jīng)改變奕短,最后需要覆蓋所有剩余的樣式宜肉。
.content-container
{
color: white;
background-color: #212121;
}
.text--alpha {
color: #50a8d8;
}
07. 可維護性
雖然剛剛完成的 Demo 看上去挺不錯,而且可以在小型的網(wǎng)站上進行維護翎碑,但這種方法對于更大的項目來說將會是一場噩夢谬返,因為其中包含有許多不同的元素,這些元素都需要被重寫日杈。同時在上面的例子中大量使用級聯(lián)遣铝,而大型系統(tǒng)可能需要更多的特異性才能定位所有元素。
08. 采取另一種方式
為了快速實現(xiàn)深色模式莉擒,只需用 CSS 濾鏡的 “invert”……
那怎樣才能解決這個問題呢酿炸?我們可以使用 CSS 濾鏡的 “invert”,將其應用于 HTML 并反轉(zhuǎn)所有顏色涨冀,從而為我們提供 “深色模式”填硕。
@media (prefers-color-scheme: dark) {
html {
filter: invert(100%);
}
}
09. 添加圖片
當然,你的照片看起來會像這樣
雖然濾鏡方法在我們文檔中的內(nèi)容上起了作用鹿鳖,但是看起來不太好 —— 例如盒子陰影也被倒置了扁眯,這看起來很奇怪。我們已經(jīng)失去了對樣式的控制栓辜,當你用了彩色背景時恋拍,會出現(xiàn)一個更大的問題垛孔∨核Γ看看你的照片變成了什么樣子。
10. 使用自定義屬性
到目前為止,我們探索過的方法要么會失去對樣式的控制狭莱,要么需要大量的維護才能確保所有內(nèi)容都在深色模式下更新僵娃。不過還有一種方法可以解決這個問題:可以用自定義屬性來定義顏色彪薛,然后使用媒體查詢覆蓋它們徽职。
11. 創(chuàng)建自定義屬性
為了使用自定義屬性,我們在:root
元素內(nèi)的CSS頂部定義它們久锥。根元素具有與 HTML 相同的范圍骤素,因此可以全局使用匙睹。我們需要確定變量名稱并定義它們的值。
:root {
--background-color: #ededed;
--page-background: #fff;
--text-color: #212121;
--color-alpha: #c3423f;
}
12. 應用自定義屬性
現(xiàn)在定義了一些可以在CSS中使用的自定義屬性济竹。我們將從正文開始痕檬,并應用背景和文本顏色。為了使用自定義屬性送浊,我們用了 var(--custom-property-name)
語法梦谜。
body {
background-color: var(--background-color);
color: var(--text-color);
}
13. 應用其余的屬性
使用相同的方法,我們還可以更新容器的background-color
和text-alpha
類的color
袭景,讓它們也使用自定義屬性⊙渥現(xiàn)在,頁面中所有得顏色都使用自定義屬性進行控制耸棒。
.content-container {
background-color: var(--page-background);
}
.text--alpha {
color: var(--color-alpha);
}
14. 重新添加媒體查詢
現(xiàn)在重新添加媒體查詢荒澡,但這次我們可以覆蓋其中的自定義屬性值。把它放在原始根定義之后榆纽,在媒體查詢中仰猖,可以簡單地為所有顏色自定義屬性選擇新值。
@media (prefers-color-scheme: dark) {
:root {
--background-color: #111;
--page-background: #212121;
--text-color: #ededed;
--color-alpha: #50a8d8;
}
}
15. 完全控制
自定義屬性使我們可以完全控制選擇自己的顏色和其他屬性奈籽。能夠?qū)撁嫒萜魃系倪吙蜿幱斑M行更新饥侵,使其在使用深色模式時不太透明。索引我們需要為頁面陰影創(chuàng)建一個新的自定義屬性衣屏。
:root {
…
--page-shadow: 0 0 12px 6px rgba
(0,0,0,0.05);
}
16. 應用陰影
現(xiàn)在我們已經(jīng)有了另一個自定義屬性躏升,接下來需要將它應用于頁面上正確的元素。然后覆蓋root元素中的值狼忱,以降低透明度膨疏。
@media (prefers-color-scheme: dark) {
:root {
…
--page-shadow:
0 0 12px 6px rgba(0,0,0,0.33)
;
}
}
.content-container {
…
box-shadow: var(--page-shadow);
}
17. 添加圖像
添加圖像并將其浮動到內(nèi)容旁邊
現(xiàn)在將圖像添加回我們的內(nèi)容,然后可以添加一些基本樣式來將圖像浮動到內(nèi)容旁邊钻弄。
img {
width: 100%;
height: auto;
float: left;
max-width: 300px;
margin-right: 1.618rem;
margin-bottom: 1.618rem;
}
可以看到佃却,由于沒有使用任何濾鏡,所以圖像在兩個主題之間不會改變窘俺。
18. 添加更多組件
現(xiàn)在我們已經(jīng)獲得了自定義屬性饲帅,可以繼續(xù)向頁面添加元素,并使用變量為它們設置樣式。讓我們創(chuàng)建一個按鈕類灶泵,并在頁面中添加一個按鈕育八。
.button {
display: inline-flex;
font-family: inherit;
background-color: var(--color-alpha);
color: var(--text-color);
padding: 1.618rem 3.236rem;
border: 0 none;
border-radius: 0.25rem;
text-decoration: none;
}
19. 創(chuàng)建按鈕懸停樣式
使用相同的變量,還可以創(chuàng)建可用于兩個主題的懸停樣式赦邻。為了實現(xiàn)這一點髓棋,當用戶將鼠標懸停在按鈕上并轉(zhuǎn)換這些屬性時,我們將反轉(zhuǎn)顏色惶洲。
.button {
…
transition: background-color 150ms,
color 150ms;
&:hover {
background-color: var(--text-color);
color: var(--color-alpha);
}
}
20. 制作按鈕自定義屬性
自定義屬性與常規(guī) CSS 元素具有相同的范圍按声,這意味著可以用更加具體的選擇器覆蓋它們√衤溃可以利用這個特性并創(chuàng)建一些作用于按鈕的變量儒喊。
.button {
--button-background: var(--color-alpha);
--button-text: var(--background-color);
background-color: var(--button-background);
color: var(--button-text);
…
}
21. 利用 scope
使用 scope 為按鈕創(chuàng)建不同的樣式和交互
我們可以利用 scope 為深色和淺色主題的按鈕創(chuàng)建不同的樣式和懸停交互”液牵可以根據(jù)媒體查詢或元素的狀態(tài)修改變量的值怀愧,而不是像往常一樣使用新值重復屬性。
.button {
…
&:hover {
--button-background: #ae3937;
@media (prefers-color-scheme: dark) {
--button-background: #2e98d1;
--button-text: var(--background-
color);
}
}
}