CSS 亮色暗色主题切换最佳实践

257 阅读2分钟

DEMO

code.juejin.cn/pen/7405122…

定义色板

:root {
  --blue: royalblue;
  --red: tomato;
  --black-100: rgba(0,0,0,1);
  --black-80: rgba(0,0,0,.8);
  --black-60: rgba(0,0,0,.6);
  --black-40: rgba(0,0,0,.4);
  --black-20: rgba(0,0,0,.2);
  --white-100: rgba(255,255,255,1);
  --white-80: rgba(255,255,255,.8);
  --white-60: rgba(255,255,255,.6);
  --white-40: rgba(255,255,255,.4);
  --white-20: rgba(255,255,255,.2);
}

预先定义好所有要用到的颜色,色板的颜色与主题无关,供主题取色

定义主题

.dark {
  color-scheme: dark;
  --bg: var(--black-100);
  --text: var(--white-100);
}

.light {
  color-scheme: light;
  --bg: var(--white-100);
  --text: var(--black-100);
}

定义了dark和light两套主题,主题内的变量是有UI语义的,变量名代表了具体UI 值是从色板取的具体颜色

主题模式实现

Theme代表了具体的主题定义,而Theme Mode是UI的主题模式 是供用户手动选择的(默认System),我们要根据UI的模式来动态切换主题定义,通常有3种模式 system light dark

System 跟随系统模式

@media(prefers-color-scheme: dark) {
  :root:not(.light):not(.dark) {
    --bg: var(--black-100);
    --text: var(--white-100);
  }
}

@media(prefers-color-scheme: light) {
  :root:not(.light):not(.dark) {
    --bg: var(--white-100);
    --text: var(--black-100);
  }
}

媒体查询自动响应系统主题来修改主题变量,代码完全是和.dark .light重复的,因为我是用纯css举例,实际开发中用scss less等工具能用@mixin复用代码

Dark、Light 亮色暗色模式

这一步就要用🤏🏻js代码来实现,只需要切换html的class name就行,亮色.light 暗色.dark

const system = document.getElementById('system')
const light = document.getElementById('light')
const dark = document.getElementById('dark')
const root = document.documentElement

system.onclick = ()=>{
  root.classList.remove('light', 'dark')
}

light.onclick = ()=>{
  root.classList.remove('dark')
  root.classList.add('light')
}

dark.onclick = ()=>{
  root.classList.remove('light')
  root.classList.add('dark')
}

持久化

用户选择模式后 下次今天要记忆上次的模式,这就需要持久化,很简单 只需要把theme mode保存到localstrage里,然后每次打开页面读取一下 然后设置模式 就可以了,具体代码不演示了。