多主题需求
自从macOS中的暗黑模式出现以后,各个应用的多主题需求也渐渐出现,本来主要讨论几种多主题的实现方案。
传统模式
传统的多主题切换依赖的是JavaScript的动态改变dom的能力,改变样式标签的href属性,来让页面加载不同的样式文件,从而达到多主题切换的目的。
我们还可以给body添加过渡效果
1 2 3
| body { transition: color 0.5s ease, background-color 0.5s ease; }
|
示例:通过监听按钮的点击,动态改变样式标签的href
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link id="theme_css" type="text/css" rel="stylesheet" href="./white.css" /> </head>
<body> <h1>关于网页的主题样式</h1>
<p> 上面这个案例和以往提供的案例有所不同。该案例按前面所讲的分成三个独立的样式文件: style.css、dark.css和light.css。尝试切换暗黑模式并重新加载页面,你会发现不匹配的样式文件仍然会被加载,只是优先级有所差异,这样做它们就不会与站点当前所需的资源竞争。 </p>
<h3>这是一个小标题</h3>
<p> 上面这个案例和以往提供的案例有所不同。该案例按前面所讲的分成三个独立的样式文件: style.css、dark.css和light.css。尝试切换暗黑模式并重新加载页面,你会发现不匹配的样式文件仍然会被加载,只是优先级有所差异,这样做它们就不会与站点当前所需的资源竞争。 </p>
<hr>
<button onclick="handleClick()">切换主题</button>
<script type="text/javascript"> let isWhite = true const handleClick = () => { if (isWhite) { isWhite = false document.getElementById('theme_css').href = './black.css' } else { isWhite = true document.getElementById('theme_css').href = './white.css' } } </script> </body>
</html>
|

CSS媒体查询
现在,可以用CSS的媒体查询prefers-color-scheme,判断用户当前的所选的主题,从而应用相应的样式
prefers-color-scheme: light 用于匹配亮白模式,prefers-color-scheme: dark 用于匹配暗黑模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @media (prefers-color-scheme: light) { h1, p { color: black; } h3 { color: blue; } html, body { width: 100%; height: 100%; background-color: white; } }
@media (prefers-color-scheme: dark) { h1, p { color: white; } h3 { color: yellow; } html, body { width: 100%; height: 100%; background-color: black; } }
|

还可以利用JavaScript检测当前环境是否支持暗黑模式,当检测支持的时候再加载暗黑模式的样式文件,从而可以避免不支持的用户加载无用的样式文件
1 2 3
| if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') { console.log('浏览器支持dark模式!(^_^)'); }
|
CSS Hack
此外,如果对细节要求不高,可以用简单的滤镜或者混合模式做统一处理,1秒变暗黑模式
filter
图片再加filter是让图片的色彩恢复正常
1 2 3 4 5 6 7
| .theme-dark { filter: invert(100) hue-rotate(180deg); }
.theme-dark img { filter: invert(100) hue-rotate(180deg); }
|

混合模式 mix-blend-mode
混合模式可以用isolate属性,设置某些元素不收混合模式的影响
1 2 3 4 5 6 7 8 9
| .dark-mode-screen { width: 100vw; height: 100vh; position: fixed; top: 0; left: 0; background: white; mix-blend-mode: difference; }
|
