变量与主题切换
变量与主题切换
CSS3 引入了自定义属性(CSS Variables),使得主题切换变得更加灵活和高效。通过定义变量并在不同场景下修改变量值,可以轻松实现动态主题切换,而无需重复编写大量样式代码。
CSS 变量的基础用法
CSS 变量以 --
开头,定义在 :root
伪类中表示全局作用域。变量通过 var()
函数调用,支持默认值设置:
:root {
--primary-color: #3498db;
--secondary-color: #2ecc71;
--text-color: #333;
}
body {
color: var(--text-color);
background-color: var(--bg-color, #f8f9fa); /* 带默认值 */
}
.button {
background: var(--primary-color);
}
动态主题切换实现
通过 JavaScript 修改根元素的变量值,可以实现实时主题切换。以下是完整示例:
<!DOCTYPE html>
<html>
<head>
<style>
:root {
--bg-color: #ffffff;
--text-color: #333333;
--primary: #4285f4;
}
body {
background: var(--bg-color);
color: var(--text-color);
transition: all 0.3s ease;
}
button {
background: var(--primary);
padding: 10px 15px;
border: none;
color: white;
}
</style>
</head>
<body>
<h1>主题切换演示</h1>
<button onclick="toggleTheme()">切换主题</button>
<script>
const themes = {
light: {
'--bg-color': '#ffffff',
'--text-color': '#333333',
'--primary': '#4285f4'
},
dark: {
'--bg-color': '#1a1a1a',
'text-color': '#f0f0f0',
'--primary': '#0d47a1'
}
};
function toggleTheme() {
const root = document.documentElement;
const currentBg = getComputedStyle(root).getPropertyValue('--bg-color').trim();
const newTheme = currentBg === '#ffffff' ? 'dark' : 'light';
Object.entries(themes[newTheme]).forEach(([property, value]) => {
root.style.setProperty(property, value);
});
}
</script>
</body>
</html>
多主题管理系统
对于复杂的主题系统,可以采用更结构化的管理方式:
/* 定义基础变量 */
:root {
--base-font-size: 16px;
--base-spacing: 8px;
}
/* 默认主题 */
[data-theme="default"] {
--primary: #3498db;
--secondary: #e74c3c;
--background: #ecf0f1;
}
/* 暗色主题 */
[data-theme="dark"] {
--primary: #2980b9;
--secondary: #c0392b;
--background: #2c3e50;
}
/* 高对比度主题 */
[data-theme="high-contrast"] {
--primary: #000000;
--secondary: #ffffff;
--background: #ffff00;
}
body {
font-size: var(--base-font-size);
padding: calc(var(--base-spacing) * 4);
background: var(--background);
}
通过修改 data-theme
属性即可切换主题:
function setTheme(themeName) {
document.documentElement.setAttribute('data-theme', themeName);
localStorage.setItem('theme', themeName); // 保存用户选择
}
// 初始化时读取保存的主题
const savedTheme = localStorage.getItem('theme') || 'default';
setTheme(savedTheme);
响应式主题适配
结合媒体查询,可以实现基于系统偏好的主题切换:
:root {
--primary: #3498db;
--background: #ffffff;
--text: #333333;
}
@media (prefers-color-scheme: dark) {
:root {
--primary: #2980b9;
--background: #1a1a1a;
--text: #f0f0f0;
}
}
/* 同时考虑用户手动选择的主题 */
[data-theme="dark"] {
--primary: #2980b9;
--background: #1a1a1a;
--text: #f0f0f0;
}
[data-theme="light"] {
--primary: #3498db;
--background: #ffffff;
--text: #333333;
}
主题切换的性能优化
- 变量分组管理:将相关变量分组定义,提高可维护性
:root {
/* 颜色变量 */
--color-primary: #3498db;
--color-secondary: #e74c3c;
/* 间距变量 */
--spacing-small: 8px;
--spacing-medium: 16px;
/* 字体变量 */
--font-body: 16px/1.5 'Helvetica', sans-serif;
}
- 使用CSS预处理器:结合Sass/Less管理变量
$themes: (
light: (
bg: #fff,
text: #333,
primary: #4285f4
),
dark: (
bg: #1a1a1a,
text: #f0f0f0,
primary: #0d47a1
)
);
@mixin theme() {
@each $theme, $map in $themes {
[data-theme="#{$theme}"] & {
$theme-map: () !global;
@each $key, $submap in $map {
$value: map-get($map, $key);
$theme-map: map-merge($theme-map, ($key: $value)) !global;
}
@content;
$theme-map: null !global;
}
}
}
@function themed($key) {
@return map-get($theme-map, $key);
}
body {
@include theme() {
background: themed('bg');
color: themed('text');
}
}
主题切换的动画效果
为提升用户体验,可以为主题切换添加平滑过渡:
:root {
--transition-time: 0.4s;
}
body {
transition:
background-color var(--transition-time) ease,
color var(--transition-time) ease;
}
button, a {
transition:
background-color var(--transition-time) ease,
border-color var(--transition-time) ease;
}
主题切换的浏览器兼容性
虽然现代浏览器普遍支持CSS变量,但仍需考虑兼容方案:
/* 回退方案 */
body {
background: #ffffff; /* 默认值 */
background: var(--bg-color, #ffffff);
}
/* 使用@supports检测支持情况 */
@supports not (--css: variables) {
body.light {
background: #ffffff;
color: #333333;
}
body.dark {
background: #1a1a1a;
color: #f0f0f0;
}
}
主题切换在组件库中的应用
组件库可以通过CSS变量实现主题定制:
/* 组件基础样式 */
.button {
padding: 0.5em 1em;
border-radius: 4px;
background: var(--button-bg, #eee);
color: var(--button-text, #333);
}
/* 主题定制 */
:root {
--button-bg: #4285f4;
--button-text: white;
--button-hover: #3367d6;
}
[data-theme="dark"] {
--button-bg: #0d47a1;
--button-text: rgba(255,255,255,0.87);
--button-hover: #1565c0;
}
主题切换的用户体验考量
- 持久化用户选择:使用localStorage保存用户偏好
- 系统偏好检测:自动匹配用户操作系统主题
- 切换控件设计:提供清晰的主题切换UI
- 过渡动画:避免突兀的颜色变化
// 检测系统主题变化
window.matchMedia('(prefers-color-scheme: dark)').addListener(e => {
setTheme(e.matches ? 'dark' : 'light');
});
// 初始化主题
function initTheme() {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
setTheme(savedTheme);
} else {
setTheme(prefersDark ? 'dark' : 'light');
}
}
主题切换的高级模式
- 部分主题切换:只改变页面特定区域的样式
.container[data-theme="dark"] {
--bg-color: #333;
--text-color: #fff;
}
- 动态主题生成:允许用户自定义主题颜色
function createCustomTheme(primary, secondary, background) {
const root = document.documentElement;
root.style.setProperty('--primary', primary);
root.style.setProperty('--secondary', secondary);
root.style.setProperty('--background', background);
}
- 主题混合:组合多个主题特性
[data-theme="dark"] [data-component-theme="light"] {
--component-bg: #ffffff;
--component-text: #333333;
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn