CSS `prefers-color-scheme` (`dark`/`light`):实现深色模式

各位观众老爷,晚上好!今天咱们来聊聊CSS里的“变色龙”—— prefers-color-scheme,以及它如何让你的网站轻松切换深色模式。准备好了吗? Let’s roll!

开场白:黑暗势力的崛起

话说,当年界面设计界,那可是明亮主题的天下。白底黑字,亮堂堂的,看着就精神。但是,随着人们对眼睛的关爱程度日益提升,以及熬夜加班的日益普遍(手动狗头),深色模式,这个黑暗势力,开始崛起。

深色模式不仅能降低屏幕亮度,减少蓝光辐射,还能在一定程度上省电(OLED屏幕)。更重要的是,它看起来更酷炫!所以,越来越多的网站和应用开始支持深色模式。

prefers-color-scheme:你的秘密武器

CSS提供了一个强大的武器,叫做 prefers-color-scheme。它是一个媒体查询,可以检测用户的系统是否设置了深色或浅色模式。有了它,你就可以根据用户的偏好,自动切换网站的颜色方案。

基本用法:侦测与响应

prefers-color-scheme 的基本用法很简单:

/* 浅色模式 (默认) */
body {
  background-color: white;
  color: black;
}

/* 深色模式 */
@media (prefers-color-scheme: dark) {
  body {
    background-color: black;
    color: white;
  }
}

这段代码的意思是:

  • 默认情况下,body的背景色是白色,文字颜色是黑色(浅色模式)。
  • 如果用户的系统设置了深色模式,那么body的背景色会变成黑色,文字颜色会变成白色。

是不是很简单?就像给你的网站装了一个自动识别颜色的眼睛一样。

进阶用法:更精细的控制

当然,你也可以更精细地控制不同元素的颜色。例如:

/* 浅色模式 */
.container {
  background-color: #f0f0f0;
  border: 1px solid #ccc;
}

.button {
  background-color: #4CAF50;
  color: white;
}

/* 深色模式 */
@media (prefers-color-scheme: dark) {
  .container {
    background-color: #333;
    border: 1px solid #666;
  }

  .button {
    background-color: #388E3C;
    color: #eee;
  }
}

这段代码分别定义了浅色模式和深色模式下,.container.button 类的样式。

prefers-color-scheme 的取值

prefers-color-scheme 可以取以下值:

含义
light 用户选择了浅色模式。
dark 用户选择了深色模式。
no-preference 用户没有明确选择颜色模式,或者浏览器不支持 prefers-color-scheme。这种情况下,浏览器会使用默认样式。

实战演练:打造一个深色模式切换按钮

虽然 prefers-color-scheme 可以自动检测用户的系统设置,但有时候,用户可能希望手动切换颜色模式。这时候,你可以添加一个切换按钮。

1. HTML 结构

<!DOCTYPE html>
<html>
<head>
  <title>深色模式切换</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <button id="theme-toggle">切换主题</button>
  <div class="container">
    <h1>Hello, World!</h1>
    <p>这是一个示例页面,用于演示深色模式切换。</p>
  </div>
  <script src="script.js"></script>
</body>
</html>

2. CSS 样式 (style.css)

/* 浅色模式 */
body {
  background-color: white;
  color: black;
  transition: background-color 0.3s ease, color 0.3s ease; /* 添加过渡效果 */
}

.container {
  background-color: #f0f0f0;
  border: 1px solid #ccc;
  padding: 20px;
}

/* 深色模式 */
body.dark-mode {
  background-color: black;
  color: white;
}

body.dark-mode .container {
  background-color: #333;
  border: 1px solid #666;
}

3. JavaScript 代码 (script.js)

const themeToggle = document.getElementById('theme-toggle');
const body = document.body;

themeToggle.addEventListener('click', () => {
  body.classList.toggle('dark-mode');
});

// 页面加载时,检测用户系统是否设置了深色模式
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
  body.classList.add('dark-mode');
}

这段代码做了以下几件事:

  • 监听按钮的点击事件。
  • 点击按钮时,切换 body 的 dark-mode 类。
  • CSS 根据 dark-mode 类来切换颜色方案。
  • 页面加载时,检测用户是否设置了深色模式,如果是,则自动添加 dark-mode 类。

代码解释:

  • transition 属性: 添加过渡效果,让颜色切换更平滑,不那么生硬。
  • window.matchMedia('(prefers-color-scheme: dark)').matches: 这个用来在页面加载时检测用户的系统偏好。如果用户设置了深色模式,matches 属性会返回 true

更完善的方案:LocalStorage 存储用户偏好

上面的代码有一个小问题:每次刷新页面,颜色模式都会重置。为了让用户手动切换的颜色模式保持不变,我们需要使用 LocalStorage 来存储用户的偏好。

修改后的 JavaScript 代码 (script.js)

const themeToggle = document.getElementById('theme-toggle');
const body = document.body;
const darkModeClass = 'dark-mode';

// 从 LocalStorage 中获取主题偏好
const savedTheme = localStorage.getItem('theme');

// 如果 LocalStorage 中有主题偏好,则应用它
if (savedTheme === 'dark') {
  body.classList.add(darkModeClass);
}

themeToggle.addEventListener('click', () => {
  body.classList.toggle(darkModeClass);

  // 保存主题偏好到 LocalStorage
  if (body.classList.contains(darkModeClass)) {
    localStorage.setItem('theme', 'dark');
  } else {
    localStorage.setItem('theme', 'light');
  }
});

// 页面加载时,检测用户系统是否设置了深色模式,但仅在 LocalStorage 没有设置时才执行
if (!localStorage.getItem('theme') && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
  body.classList.add(darkModeClass);
  localStorage.setItem('theme', 'dark'); //同时保存到localStorage
}

这段代码做了以下修改:

  • 从 LocalStorage 中读取用户的主题偏好。
  • 如果 LocalStorage 中有主题偏好,则应用它。
  • 点击按钮时,将当前的主题偏好保存到 LocalStorage。
  • 页面加载时,如果LocalStorage没有存储任何主题偏好, 才会检测用户的系统设置,如果用户设置了深色模式,则自动添加 dark-mode 类,并保存到LocalStorage。

重要提示:

  • 浏览器兼容性: prefers-color-scheme 的兼容性非常好,主流浏览器都支持。

  • CSS变量(Custom Properties): 使用 CSS 变量可以更方便地管理颜色方案。例如:

    :root {
      --bg-color: white;
      --text-color: black;
    }
    
    body {
      background-color: var(--bg-color);
      color: var(--text-color);
    }
    
    @media (prefers-color-scheme: dark) {
      :root {
        --bg-color: black;
        --text-color: white;
      }
    }
  • 图片处理: 深色模式下,有些图片可能需要调整。例如,浅色背景的 logo 在深色背景下可能看不清楚。你可以使用 CSS 的 filter 属性来调整图片的颜色,或者使用 <picture> 元素来加载不同的图片。

  • 避免硬编码颜色值: 尽量使用 CSS 变量或者语义化的类名,方便维护和修改。

  • 测试!测试!测试! 在不同的浏览器和设备上测试你的深色模式实现,确保一切正常。

深色模式的未来

深色模式已经成为一种趋势,越来越多的网站和应用将会支持它。prefers-color-scheme 是一个非常强大的工具,可以帮助你轻松地实现深色模式。

总结:

  • prefers-color-scheme 是一个 CSS 媒体查询,可以检测用户的颜色模式偏好。
  • 你可以使用 prefers-color-scheme 来自动切换网站的颜色方案。
  • 可以使用 JavaScript 和 LocalStorage 来实现手动切换颜色模式的功能。
  • 使用 CSS 变量可以更方便地管理颜色方案。
  • 记得测试你的深色模式实现!

表格总结:

特性 描述 代码示例
prefers-color-scheme CSS媒体查询,检测用户系统颜色模式偏好。 css @media (prefers-color-scheme: dark) { body { background-color: black; color: white; } }
CSS变量 (Custom Properties) 用于存储颜色值,方便维护和修改。 css :root { --bg-color: white; --text-color: black; } body { background-color: var(--bg-color); color: var(--text-color); } @media (prefers-color-scheme: dark) { :root { --bg-color: black; --text-color: white; } }
JavaScript切换按钮 允许用户手动切换颜色模式。 javascript const themeToggle = document.getElementById('theme-toggle'); const body = document.body; themeToggle.addEventListener('click', () => { body.classList.toggle('dark-mode'); }); if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { body.classList.add('dark-mode'); }
LocalStorage存储偏好 存储用户选择的颜色模式,避免刷新后重置。 javascript const themeToggle = document.getElementById('theme-toggle'); const body = document.body; const darkModeClass = 'dark-mode'; const savedTheme = localStorage.getItem('theme'); if (savedTheme === 'dark') { body.classList.add(darkModeClass); } themeToggle.addEventListener('click', () => { body.classList.toggle(darkModeClass); if (body.classList.contains(darkModeClass)) { localStorage.setItem('theme', 'dark'); } else { localStorage.setItem('theme', 'light'); } }); if (!localStorage.getItem('theme') && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { body.classList.add(darkModeClass); localStorage.setItem('theme', 'dark'); }

结束语:拥抱黑暗,拥抱未来

好了,今天的讲座就到这里。希望大家能够掌握 prefers-color-scheme 这个强大的武器,让你的网站更加人性化,更加酷炫!记住,拥抱黑暗,才能拥抱未来! 感谢大家的观看,下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注