当前位置: 首页 > news >正文

【前端从0到1实战】第7篇:构建“深色模式切换”与本地存储 (Dark Mode LocalStorage)

欢迎来到本系列的第7篇。在之前的文章中,我们主要关注组件的内部逻辑。今天,我们将把视野扩大到整个网站的架构。

深色模式(Dark Mode)不仅仅是一个“开关”,它涉及到 CSS 架构设计的核心思想——变量化。同时,为了让网站“记住”用户的选择,我们将第一次接触浏览器的LocalStorage(本地存储)。

本篇我们将实现:

基于 CSS 变量 的主题系统。

一个平滑切换的“日/夜”开关。

使用 JS 读取和保存用户偏好。

第一部分:HTML 结构搭建 (语义化与开关)

HTML 结构相对简单。我们主要需要两部分:

页面内容:用于展示主题切换后的效果(如标题、卡片、文字)。

切换开关:一个用于触发切换的按钮。

<body>
<!-- 1. 顶部导航栏 -->
<nav class="navbar"><div class="logo">MyBrand</div><!-- 主题切换开关 aria-label 是为了无障碍访问--><button id="theme-toggle" class="theme-btn" aria-label="切换主题"><!-- 默认显示月亮图标 (代表点击进入深色模式) --><span class="icon">🌙</span><span class="text">深色模式</span></button>
</nav><!-- 2. 主要内容区域 -->
<main class="container"><div class="hero-section"><h1>欢迎来到我的博客</h1><p>这是一个演示 CSS 变量和深色模式切换的页面。</p></div><div class="card-grid"><!-- 卡片 1 --><div class="card"><h2>文章标题 1</h2><p>这是一些示例文本。在深色模式下,背景变黑,文字变白。</p><a href="#" class="link">阅读更多</a></div><!-- 卡片 2 --><div class="card"><h2>文章标题 2</h2><p>CSS 变量让这一切变得非常简单且高效。</p><a href="#" class="link">阅读更多</a></div></div></main>
</body>

第二部分:CSS 样式 (CSS 变量的魔力)

这是本篇的核心。我们不再直接写死颜色(如 #ffffff 或 #000000),而是定义变量。

逻辑如下:

在 :root (默认状态) 下定义一套“浅色”变量。

在 [data-theme="dark"] 状态下重新定义这套变量为“深色”值。

在具体的 CSS 规则中,只使用 var(--variable-name)。

/* --- 1. 定义变量系统 --- */

/* 默认 (浅色) 主题 /
:root {
/
背景色 */
--bg-body: #f4f7f6;
--bg-card: #ffffff;
--bg-nav: #ffffff;

/* 文本色 */
--text-primary: #333333;
--text-secondary: #666666;/* 强调色 */
--accent-color: #007bff;/* 边框与阴影 */
--border-color: #e1e4e8;
--shadow: 0 4px 12px rgba(0,0,0,0.08);

}

/* 深色主题 (通过 data-theme="dark" 属性激活) */
[data-theme="dark"] {
--bg-body: #1a1a1a;
--bg-card: #2d2d2d;
--bg-nav: #2d2d2d;

--text-primary: #ffffff;
--text-secondary: #b0b0b0;--accent-color: #4dabf7; /* 深色模式下通常颜色要稍微亮一点 */--border-color: #444444;
--shadow: 0 4px 12px rgba(0,0,0,0.3);

}

/* --- 2. 应用变量 --- */

body {
background-color: var(--bg-body);
color: var(--text-primary);
font-family: -apple-system, sans-serif;
/* 核心:添加 transition 让颜色切换平滑过渡 */
transition: background-color 0.3s ease, color 0.3s ease;
margin: 0;
}

.navbar {
background-color: var(--bg-nav);
border-bottom: 1px solid var(--border-color);
padding: 15px 30px;
display: flex;
justify-content: space-between;
align-items: center;
transition: background-color 0.3s ease, border-color 0.3s ease;
}

.card {
background-color: var(--bg-card);
border: 1px solid var(--border-color);
box-shadow: var(--shadow);
padding: 25px;
border-radius: 8px;
transition: background-color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
}

.card h2 { margin-top: 0; }

.card p { color: var(--text-secondary); }

.link { color: var(--accent-color); text-decoration: none; }

/* --- 开关按钮样式 --- */
.theme-btn {
background: transparent;
border: 1px solid var(--border-color);
color: var(--text-primary);
padding: 8px 16px;
border-radius: 20px;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
}

.theme-btn:hover {
background-color: var(--bg-body);
}

/* 布局辅助 */
.container { max-width: 800px; margin: 40px auto; padding: 0 20px; }
.card-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }

第三部分:JS 交互逻辑 (LocalStorage)

JavaScript 的任务不仅仅是切换类名,更重要的是持久化用户的选择。

逻辑流程:

初始化:页面加载时,检查 localStorage。如果有保存的设置,立即应用。

切换:点击按钮时,切换 html 标签上的 data-theme 属性。

保存:将当前的状态('dark' 或 'light')写入 localStorage。

document.addEventListener('DOMContentLoaded', () => {

// 1. 获取 DOM 元素
const toggleBtn = document.getElementById('theme-toggle');
const toggleIcon = toggleBtn.querySelector('.icon');
const toggleText = toggleBtn.querySelector('.text');// 我们将把 data-theme 属性放在 <html> 标签上
const htmlElement = document.documentElement;// --- 辅助函数:更新按钮 UI ---
const updateButtonUI = (isDark) => {if (isDark) {toggleIcon.textContent = '☀';toggleText.textContent = '浅色模式';} else {toggleIcon.textContent = '🌙';toggleText.textContent = '深色模式';}
};// --- 2. 初始化:检查本地存储 ---
// 检查用户之前是否选过
const savedTheme = localStorage.getItem('myAppTheme');// 如果之前保存了 'dark',则立即应用
if (savedTheme === 'dark') {htmlElement.setAttribute('data-theme', 'dark');updateButtonUI(true);
} else {// 默认是浅色,无需操作 (或者也可以显式设置 'light')updateButtonUI(false);
}// --- 3. 绑定点击事件 ---
toggleBtn.addEventListener('click', () => {// 检查当前是否是深色模式const currentTheme = htmlElement.getAttribute('data-theme');if (currentTheme === 'dark') {// -> 切换为浅色htmlElement.setAttribute('data-theme', 'light');localStorage.setItem('myAppTheme', 'light'); // 保存到本地updateButtonUI(false);} else {// -> 切换为深色htmlElement.setAttribute('data-theme', 'dark');localStorage.setItem('myAppTheme', 'dark'); // 保存到本地updateButtonUI(true);}});

});

总结

恭喜!您构建了一个现代化的、具备记忆功能的深色模式系统。

我们学到了:

CSS 变量 (:root):这是现代 CSS 最强大的功能之一,它彻底改变了我们管理颜色的方式。

属性选择器 ([data-theme="..."]):利用 HTML 属性来驱动 CSS 样式的变化。

LocalStorage:如何使用简单的 setItem 和 getItem 让网页拥有“记忆”,极大地提升了用户体验。

这套逻辑是通用的,您可以将其应用到任何规模的 Web 项目中。

http://www.jsqmd.com/news/51836/

相关文章:

  • 价值原语化与LLM协同驱动:法律智能的构建路径与范式探析
  • 2025年专业的信号发生器品牌TOP5推荐
  • 2025 年木塑地板厂家最新推荐,聚焦资质、案例、售后的五家品牌深度解读室外木塑地板厂家/共挤木塑地板厂家/wpc木塑地板厂家/防腐木塑地板厂家
  • 2025年下半年溶剂油墨/玻璃油墨/水性油墨/UV油墨/溶剂耗材推荐前十指南:专业选购与口碑解析
  • 实验四截图
  • 光谱传感芯片技术让日常设备具备超级视觉
  • Linux的进程控制 - 教程
  • 第九届能源、环境与材料科学国际学术会议(EEMS 2025)
  • 2025年卧室简约吊灯生产厂家推荐:助你提升家居品质
  • 【webpack】Webpack 最常用的 20 道面试题总结 - 教程
  • 2025年现代智慧家居照明工厂推荐
  • 2025留学中介排行榜 TOP10:谁是真文书实力派?
  • P29_利用GUP训练(一)
  • 2025年11月婚姻律师排名榜:离婚律师综合对比
  • 十大留学机构排名 TOP10:2025 申请季破局密钥解密
  • 2025十大留学中介排名TOP10:申请破局的文书制胜法则
  • 市面主流公寓管理系统推荐,公寓管理系统软件排名
  • 2025年11月iso9001认证/iso三体系认证/CE认证/iatf16949认证/iso27001认证厂家推荐:专业选择与深度解析
  • 2025年定制离焦镜品牌推荐榜单:定制离焦、定制离焦镜、个性化定制离焦镜引领技术新趋势
  • 留学机构排行榜TOP10:2025申请季的黄金法则!
  • 留学中介排行榜TOP10:谁是2025申请季的王牌?
  • 2025年大型镀锌锅优质厂家权威推荐榜单:热镀锌锅设备/专业镀锌锅/工业镀锌锅设备源头厂家精选
  • what are you saying?
  • 2025 年最新推荐钢结构厂家排行榜:覆盖设计施工制造全领域,精选高性能高品质靠谱厂家钢结构施工/钢结构厂房/钢结构平台/钢结构安装/钢结构仓库/重型钢结构/钢结构雨棚公司推荐
  • 2025年幼儿园设计厂家引领者,飞友以安全重塑行业标准
  • 2025留学中介排名TOP10:留学机构文书申请优势大公开!
  • 留学中介机构排名TOP10怎么选?哪家能助申请
  • 2025 年保温板源头厂家最新推荐排行榜:国家级高新技术企业领衔,优质品牌地暖 / 环保保温板精选
  • 川渝火锅团建地TOP10:2025年人气排行,成都火锅/鸳鸯火锅/特色美食/重庆火锅/冒菜nbsp;川渝火锅聚餐地点营业到几点
  • 2025年11月深圳装修设计公司最新推荐,办公室、酒店、展厅、写字楼、厂房、公寓、店铺工装装修多维度综合考量