给网站添加暗黑模式指南
导读:给网站添加暗黑模式是随着macOS中的暗黑模式(Dark Mode)出现之后的一个热门话题。社区中有关于这方面的讨论也很多,都在围绕着怎么给网站添加暗黑模式。今天在这篇文章再次和大家一起聊聊这个已久的话题,不同的是,这篇文章将和大家从不同的角度来聊怎么给网站添加暗黑模式。感兴趣的同学,请继续往下阅读。
<!-- HTML -->
<link type="text/css" rel="stylesheet" media="all" href="../theme1.css" id="theme_css" />
// Script
document.getElementById('buttonID').addEventListener('click', function(){ document.getElementById('theme_css').href = '../theme2.css';
})
▐ 媒体查询prefers-color-scheme
@media (prefers-reduced-motion: reduce) {
button {
animation: none;
}
}
@media (prefers-reduced-motion: no-preference) {
button {
animation: vibrate 0.3s linear infinite both;
}
}
<link rel="stylesheet" href="animations.css" media="(prefers-reduced-motion: no-preference)" />
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
mediaQuery.addEventListener('change', () => {
console.log(mediaQuery.media, mediaQuery.matches);
// ...
});
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.001s;
transition-duration: 0.001s;
}
}
no-preference:表示用户未指定操作系统主题。其作为 布尔值 时以false输出
light:表示用户的操作系统是浅色主题(light)
dark:表示用户的操作系统是深色主题(dark)
@media (prefers-color-scheme: dark) {
:root {
--background-color: #111416
--text-color: #ccc;
--link-color: #f96;
}
}
:root {
--background-color: #fff;
--text-color: #333;
--link-color: #b52;
}
body {
background-color: var(--background-color);
color: var(--text-color);
}
a {
color: var(--link-color);
}
if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
console.log('浏览器支持dark模式!(^_^)');
}
style.css:网站上普通样式(通用样式)
dark.css:暗色系所需样式规则
light.css:亮色系所需样式规则
<!-- Script --><script> if (window.matchMedia('(prefers-color-scheme: dark)').media === 'not all') { document.documentElement.style.display = 'none'; document.head.insertAdjacentHTML( 'beforeend', '<link rel="stylesheet" href="/light.css" onload="document.documentElement.style.display = \'\'">' ); }</script><!-- HTML --><link rel="stylesheet" href="/style.css"><link rel="stylesheet" href="/dark.css" media="(prefers-color-scheme: dark)"><link rel="stylesheet" href="/light.css" media="(prefers-color-scheme: no-preference), (prefers-color-scheme: light)">
// dark.css
:root {
--background-color: #111416
--text-color: #ccc;
--link-color: #f96;
}
// light.css
:root {
--background-color: #fff;
--text-color: #333;
--link-color: #b52;
}
// style.css
body {
background-color: var(--background-color);
color: var(--text-color);
}
a {
color: var(--link-color);
}
▐ CSS的新特性color-scheme
/* dark.css */
:root {
--color: rgb(250, 250, 250);
--background-color: rgb(5, 5, 5);
--link-color: rgb(0, 188, 212);
--main-headline-color: rgb(233, 30, 99);
--accent-background-color: rgb(0, 188, 212);
--accent-color: rgb(5, 5, 5);
}
/* light.css */
:root {
--color: rgb(5, 5, 5);
--background-color: rgb(250, 250, 250);
--link-color: rgb(0, 0, 238);
--main-headline-color: rgb(0, 0, 192);
--accent-background-color: rgb(0, 0, 238);
--accent-color: rgb(250, 250, 250);
}
/* style.css */
:root {
color-scheme: light dark;
}
body {
color: var(--color);
background-color: var(--background-color);
}
<meta name="supported-color-schemes" content="light dark">
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');darkModeMediaQuery.addListener((e) => { const darkModeOn = e.matches; console.log(`Dark mode is ${darkModeOn ? 'on' : 'off'}.`);});
▐ CSS混合模式来助攻
.theme-dark { filter: invert(100) hue-rotate(180deg); } .theme-dark img { filter: invert(100) hue-rotate(180deg); }
.dark-mode-screen {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
background: white;
mix-blend-mode: difference;
}
.twitter-logo,
.emoji {
isolation: isolate;
}
▐ 其他细节
// 粗暴模式
@media (prefers-color-scheme: dark) {
img {
opacity: 0.65;
}
img:hover {
opacity: 1;
}
}
// 温柔模式
@media (prefers-color-scheme: dark) {
img {
filter: brightness(.8) contrast(1.2);
}
}
@media (prefers-color-scheme: dark) {
img:not([src*=".svg"]) {
filter: brightness(.8) contrast(1.2);
}
}
// dark.css
:root {
--brightness: brightness(.8);
--contrast: contrast(1.2);
--image-filter: var(--brightness) var(--contrast);
}
// JS
document.documentElement.style.setProperty('--image-filter', value);
<picture>
<source media="prefers-color-scheme: dark" srcset="./dark.webp" />
<source media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" srcset="./light.webp" />
<img src="./light.png" alt="map" />
</picture>
/* dark.css */
:root {
--icon-filter: invert(100%);
--icon-filter_hover: invert(40%);
}
img[src*=".svg"] {
filter: var(--icon-filter);
}
/* light.css */
:root {
--icon-filter_hover: invert(60%);
}
/* style.css */
img[src*=".svg"]:hover {
filter: var(--icon-filter_hover);
}
<svg xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round"
>
<circle cx="12" cy="12" r="10"/>
<circle cx="12" cy="12" r="4"/>
<line x1="21.17" y1="8" x2="12" y2="8"/>
<line x1="3.95" y1="6.06" x2="8.54" y2="14"/>
<line x1="10.88" y1="21.94" x2="15.46" y2="14"/>
</svg>
@media (prefers-color-scheme: dark) {
:root {
--background-color: #111416
--text-color: #ccc;
--link-color: #f96;
}
svg {
color: var(--text-color)
}
}
/* dark.css */
:root {
--color: rgb(250, 250, 250);
--background-color: rgb(5, 5, 5);
--link-color: rgb(0, 188, 212);
--main-headline-color: rgb(233, 30, 99);
--accent-background-color: rgb(0, 188, 212);
--accent-color: rgb(5, 5, 5);
}
/* light.css */
:root {
--color: rgb(5, 5, 5);
--background-color: rgb(250, 250, 250);
--link-color: rgb(0, 0, 238);
--main-headline-color: rgb(0, 0, 192);
--accent-background-color: rgb(0, 0, 238);
--accent-color: rgb(250, 250, 250);
}
/* style.css */
:root {
color-scheme: light dark;
}
body {
color: var(--color);
background-color: var(--background-color);
}
svg {
color: var(--color);
}
body {
--duration: 0.5s;
--timing: ease;
color: var(--color);
background-color: var(--background-color);
transition: color var(--duration) var(--timing), background-color var(--duration) var(--timing);
}
在网站上提供相应的切换按钮(比如一个tab选项卡,也可以是一个radio按钮),方便用户自行选择
该JS可以对系统级别做监听,如果用户从系统级别开启了暗黑模式,那么就把样式文件切换到dark.css下
还可以根据时间来做一个dark/light模式的切换,比如说白天采用light模式,晚上使用dark模式
和CSS实现dark/light模式切换一样,还可以在JS中加上transition效果,让模式在切换的过程有一个过渡效果
Hello darkness, my old friend
Implementing Dark Mode For My Website
Dark mode
A guide to implementing dark modes on websites
How to Enable Dark Mode for Google Chrome
Dark Mode in CSS
Night Mode with Mix Blend Mode: Difference
CSS-only dark mode
Designing for Dark Mode
Supporting macOS Mojave’s Dark Mode on the web
Create A Dark/Light Mode Switch with CSS Variables
Firefox 67: Dark Mode CSS, WebRender, and more
How to create a dark theme without breaking things: learning with the Yandex Mail team
END