css自定义属性实现主题切换

416 阅读1分钟

CSS自定义属性

  • css自定义属性 是一个名称以两个连字符( - )开头的属性,如 --color。
  • 定义后可以使用 var() 引用的变量
/* light主题 */
/* public/css/light.css */
:root[data-theme="light"] {
  --font-color: #000;
  --background-color: #fff;
}

/* dark主题 */
/* public/css/dark.css */
:root[data-theme="light"] {
  --font-color: #fff;
  --background-color: #000;
}

:root

  • 在 :root 选择器中定义自定义属性意味着它们可以作用于全局文档中所有元素。 :root 是一个CSS伪类,它匹配文档的根元素 – <html>元素。它类似于 html 选择器,但具有更高的优先级。
  • 可以在文档中的任何位置访问 :root 中的自定义属性的值
div {
    color: var(--font-color);
    background-color: var(--background-color);
}

js属性切换

onThemeChange(theme) {
  let dataTheme = ''
  switch (theme) {
    case THEME_LIGHT: 
      dataTheme = 'light' 
      break 
    case THEME_DARK: 
      dataTheme = 'dark' 
      break 
    case THEME_SYSTEM: 
      let matchMedia = window.matchMedia('(prefers-color-scheme: dark)')
      dataTheme = matchMedia.matches ? 'dark' : 'light' 
      break
  }
  document.documentElement.setAttribute('data-theme', dataTheme);
}

主题跟随系统

prefers-color-scheme是 css 媒体特性 @media 中用于检测用户是否有将系统的主题色设置为亮色或者暗色

// 适配系统主题监听
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { this.onThemeChange('THEME_SYSTEM') })
// 取消监听
window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', e => { this.onThemeChange('THEME_SYSTEM') })

index.html引入

<html theme="light">
  <head>
    <link rel="stylesheet" href="<%= process.env.VUE_APP_CDN_URL %>/css/light.css">
    <link rel="stylesheet" href="<%= process.env.VUE_APP_CDN_URL %>/css/dark.css">
  </head>
</html>