CSS 变量教程
1. CSS 变量概述
CSS 变量(也称为自定义属性)是 CSS3 中引入的一项强大功能,它允许你定义可重用的值,并在整个样式表中引用这些值。使用 CSS 变量可以使你的代码更加简洁、可维护,并且可以实现一些以前需要 JavaScript 才能实现的动态样式效果。
在本教程中,我们将探讨 CSS 变量的基本用法和高级特性,以及如何在实际项目中有效地使用它们。
2. 核心知识点
2.1 变量定义和使用
CSS 变量通过 -- 前缀定义,使用 var() 函数引用。
/* 定义变量 */
:root {
--primary-color: #3498db;
--secondary-color: #2ecc71;
--font-size: 16px;
--spacing: 10px;
--border-radius: 4px;
}
/* 使用变量 */
.element {
color: var(--primary-color);
font-size: var(--font-size);
margin: var(--spacing);
border-radius: var(--border-radius);
}
/* 使用变量并提供默认值 */
.another-element {
color: var(--primary-color, blue); /* 如果 --primary-color 未定义,使用 blue */
background-color: var(--accent-color, #f1c40f); /* 如果 --accent-color 未定义,使用 #f1c40f */
}2.2 变量作用域
CSS 变量的作用域由定义它们的选择器决定。在 :root 伪类中定义的变量是全局变量,可以在整个文档中使用。在其他选择器中定义的变量是局部变量,只能在该选择器及其子元素中使用。
/* 全局变量 */
:root {
--global-color: #3498db;
}
/* 局部变量 */
.container {
--local-color: #2ecc71;
color: var(--local-color); /* 可以使用局部变量 */
border-color: var(--global-color); /* 可以使用全局变量 */
}
.child {
color: var(--local-color); /* 可以继承父元素的局部变量 */
}
.sibling {
color: var(--local-color); /* 不能使用其他元素的局部变量,会使用默认值 */
}2.3 变量继承
CSS 变量会从父元素继承,这意味着子元素可以使用父元素中定义的变量。
.parent {
--parent-color: #3498db;
color: var(--parent-color);
}
.child {
/* 继承父元素的变量 */
border-color: var(--parent-color);
}
.grandchild {
/* 继承父元素的变量,间接继承祖父元素的变量 */
background-color: var(--parent-color);
}2.4 动态修改变量
CSS 变量可以通过 JavaScript 动态修改,这使得它们非常适合用于主题切换、响应式设计等场景。
// 获取根元素
const root = document.documentElement;
// 设置变量值
root.style.setProperty('--primary-color', '#e74c3c');
// 获取变量值
const primaryColor = getComputedStyle(root).getPropertyValue('--primary-color');
console.log(primaryColor); // 输出: #e74c3c
// 切换主题
function setTheme(theme) {
if (theme === 'light') {
root.style.setProperty('--background-color', '#ffffff');
root.style.setProperty('--text-color', '#333333');
root.style.setProperty('--primary-color', '#3498db');
} else if (theme === 'dark') {
root.style.setProperty('--background-color', '#2c3e50');
root.style.setProperty('--text-color', '#ffffff');
root.style.setProperty('--primary-color', '#3498db');
}
}
// 调用函数切换主题
setTheme('dark');2.5 变量的计算
CSS 变量可以与 calc() 函数结合使用,实现动态计算值。
:root {
--base-font-size: 16px;
--spacing-unit: 8px;
}
.element {
font-size: var(--base-font-size);
margin: calc(var(--spacing-unit) * 2); /* 16px */
padding: calc(var(--spacing-unit) * 1.5); /* 12px */
width: calc(100% - (var(--spacing-unit) * 4)); /* 100% - 32px */
}
.large-element {
font-size: calc(var(--base-font-size) * 1.2); /* 19.2px */
}
.small-element {
font-size: calc(var(--base-font-size) * 0.8); /* 12.8px */
}3. 实用案例分析
3.1 主题切换
场景: 创建一个支持亮色和暗色主题切换的网页。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>主题切换示例</title>
<style>
/* 定义默认主题变量 */
:root {
--background-color: #ffffff;
--text-color: #333333;
--primary-color: #3498db;
--secondary-color: #2ecc71;
--accent-color: #f1c40f;
--border-color: #dddddd;
--card-background: #f9f9f9;
--header-background: #f5f5f5;
--footer-background: #f5f5f5;
--transition-speed: 0.3s;
}
/* 暗色主题变量 */
[data-theme="dark"] {
--background-color: #1a1a1a;
--text-color: #e0e0e0;
--primary-color: #3498db;
--secondary-color: #2ecc71;
--accent-color: #f39c12;
--border-color: #333333;
--card-background: #2c2c2c;
--header-background: #232323;
--footer-background: #232323;
}
/* 全局样式 */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
background-color: var(--background-color);
color: var(--text-color);
transition: background-color var(--transition-speed), color var(--transition-speed);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
header {
background-color: var(--header-background);
padding: 20px 0;
border-bottom: 1px solid var(--border-color);
transition: background-color var(--transition-speed), border-color var(--transition-speed);
}
nav {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 24px;
font-weight: bold;
color: var(--primary-color);
transition: color var(--transition-speed);
}
.nav-links {
display: flex;
gap: 20px;
}
.nav-links a {
color: var(--text-color);
text-decoration: none;
transition: color var(--transition-speed);
}
.nav-links a:hover {
color: var(--primary-color);
}
.theme-toggle {
background-color: var(--primary-color);
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
transition: background-color var(--transition-speed);
}
.theme-toggle:hover {
opacity: 0.9;
}
section {
padding: 60px 0;
}
.section-title {
font-size: 36px;
margin-bottom: 40px;
text-align: center;
color: var(--primary-color);
transition: color var(--transition-speed);
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 30px;
}
.card {
background-color: var(--card-background);
border-radius: 8px;
padding: 30px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
transition: background-color var(--transition-speed);
}
.card-title {
font-size: 20px;
margin-bottom: 15px;
color: var(--primary-color);
transition: color var(--transition-speed);
}
.card-text {
margin-bottom: 20px;
}
.btn {
display: inline-block;
padding: 10px 20px;
background-color: var(--primary-color);
color: white;
text-decoration: none;
border-radius: 4px;
transition: background-color var(--transition-speed);
}
.btn:hover {
opacity: 0.9;
}
footer {
background-color: var(--footer-background);
padding: 40px 0;
border-top: 1px solid var(--border-color);
text-align: center;
transition: background-color var(--transition-speed), border-color var(--transition-speed);
}
@media (max-width: 768px) {
.nav-links {
display: none;
}
.card-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<header>
<div class="container">
<nav>
<div class="logo">My Website</div>
<div class="nav-links">
<a href="#">首页</a>
<a href="#">关于我们</a>
<a href="#">产品中心</a>
<a href="#">联系我们</a>
</div>
<button class="theme-toggle" id="themeToggle">切换主题</button>
</nav>
</div>
</header>
<section>
<div class="container">
<h1 class="section-title">欢迎来到我们的网站</h1>
<div class="card-grid">
<div class="card">
<h2 class="card-title">专业设计</h2>
<p class="card-text">我们提供专业的网页设计服务,为您的企业打造独特的品牌形象。我们的设计师团队拥有丰富的经验,能够根据您的需求创造出美观、实用的网页设计。</p>
<a href="#" class="btn">了解更多</a>
</div>
<div class="card">
<h2 class="card-title">前端开发</h2>
<p class="card-text">我们的前端开发团队精通 HTML、CSS、JavaScript 等前端技术,能够将设计转化为功能完善、响应式的网页应用。我们注重代码质量和用户体验,确保网站在各种设备上都能正常运行。</p>
<a href="#" class="btn">了解更多</a>
</div>
<div class="card">
<h2 class="card-title">后端开发</h2>
<p class="card-text">我们提供专业的后端开发服务,为您的网站搭建稳定、安全的服务器端系统。我们的后端开发团队熟悉各种编程语言和框架,能够根据您的需求选择最合适的技术方案。</p>
<a href="#" class="btn">了解更多</a>
</div>
</div>
</div>
</section>
<footer>
<div class="container">
<p>© 2026 My Website. 保留所有权利。</p>
</div>
</footer>
<script>
const themeToggle = document.getElementById('themeToggle');
const html = document.documentElement;
// 检查本地存储中的主题设置
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
html.setAttribute('data-theme', savedTheme);
}
// 切换主题
themeToggle.addEventListener('click', () => {
const currentTheme = html.getAttribute('data-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
html.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
});
</script>
</body>
</html>效果: 网页支持亮色和暗色主题切换,切换时会平滑过渡,并且主题设置会保存在本地存储中。
3.2 响应式设计
场景: 使用 CSS 变量创建响应式设计,根据屏幕尺寸自动调整布局和样式。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>响应式设计示例</title>
<style>
/* 定义变量 */
:root {
--base-font-size: 16px;
--spacing-unit: 8px;
--container-max-width: 1200px;
--header-height: 60px;
--footer-height: 80px;
--primary-color: #3498db;
--secondary-color: #2ecc71;
--text-color: #333333;
--background-color: #ffffff;
--border-color: #dddddd;
--card-padding: 20px;
--card-border-radius: 8px;
--grid-gap: 20px;
}
/* 响应式变量 */
@media (max-width: 1200px) {
:root {
--container-max-width: 960px;
}
}
@media (max-width: 992px) {
:root {
--container-max-width: 720px;
--card-padding: 15px;
--grid-gap: 15px;
}
}
@media (max-width: 768px) {
:root {
--container-max-width: 540px;
--base-font-size: 14px;
--spacing-unit: 6px;
--header-height: 50px;
--footer-height: 60px;
}
}
@media (max-width: 576px) {
:root {
--container-max-width: 100%;
--card-padding: 10px;
--grid-gap: 10px;
}
}
/* 全局样式 */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
font-size: var(--base-font-size);
color: var(--text-color);
background-color: var(--background-color);
}
.container {
max-width: var(--container-max-width);
margin: 0 auto;
padding: 0 calc(var(--spacing-unit) * 2);
}
header {
height: var(--header-height);
background-color: var(--primary-color);
color: white;
display: flex;
align-items: center;
position: sticky;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.logo {
font-size: calc(var(--base-font-size) * 1.5);
font-weight: bold;
}
nav ul {
display: flex;
list-style: none;
gap: calc(var(--spacing-unit) * 3);
}
nav a {
color: white;
text-decoration: none;
transition: opacity 0.3s;
}
nav a:hover {
opacity: 0.8;
}
.mobile-menu-btn {
display: none;
background: none;
border: none;
color: white;
font-size: 24px;
cursor: pointer;
}
section {
padding: calc(var(--spacing-unit) * 10) 0;
}
.section-title {
font-size: calc(var(--base-font-size) * 2.5);
margin-bottom: calc(var(--spacing-unit) * 5);
text-align: center;
color: var(--primary-color);
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: var(--grid-gap);
}
.card {
background-color: white;
border: 1px solid var(--border-color);
border-radius: var(--card-border-radius);
padding: var(--card-padding);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.card-title {
font-size: calc(var(--base-font-size) * 1.2);
margin-bottom: calc(var(--spacing-unit) * 2);
color: var(--primary-color);
}
.card-text {
margin-bottom: calc(var(--spacing-unit) * 3);
}
.btn {
display: inline-block;
padding: calc(var(--spacing-unit) * 1.5) calc(var(--spacing-unit) * 3);
background-color: var(--primary-color);
color: white;
text-decoration: none;
border-radius: 4px;
transition: background-color 0.3s;
}
.btn:hover {
background-color: #2980b9;
}
footer {
height: var(--footer-height);
background-color: #333;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
/* 移动设备菜单 */
@media (max-width: 768px) {
.mobile-menu-btn {
display: block;
}
nav ul {
position: fixed;
top: var(--header-height);
left: 0;
right: 0;
background-color: var(--primary-color);
flex-direction: column;
align-items: center;
padding: calc(var(--spacing-unit) * 3) 0;
gap: calc(var(--spacing-unit) * 2);
transform: translateY(-150%);
transition: transform 0.3s;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
}
nav ul.active {
transform: translateY(0);
}
}
</style>
</head>
<body>
<header>
<div class="container header-content">
<div class="logo">My Website</div>
<nav>
<button class="mobile-menu-btn" id="mobileMenuBtn">☰</button>
<ul id="navMenu">
<li><a href="#">首页</a></li>
<li><a href="#">关于我们</a></li>
<li><a href="#">产品中心</a></li>
<li><a href="#">联系我们</a></li>
</ul>
</nav>
</div>
</header>
<section>
<div class="container">
<h1 class="section-title">响应式设计示例</h1>
<div class="card-grid">
<div class="card">
<h2 class="card-title">响应式布局</h2>
<p class="card-text">使用 CSS 变量和媒体查询创建响应式布局,根据屏幕尺寸自动调整内容的大小和排列方式,确保在各种设备上都能提供良好的用户体验。</p>
<a href="#" class="btn">了解更多</a>
</div>
<div class="card">
<h2 class="card-title">灵活的间距</h2>
<p class="card-text">使用 CSS 变量定义间距单位,在不同屏幕尺寸下自动调整间距大小,保持页面的美观和一致性。</p>
<a href="#" class="btn">了解更多</a>
</div>
<div class="card">
<h2 class="card-title">自适应字体</h2>
<p class="card-text">使用 CSS 变量定义基础字体大小,在不同屏幕尺寸下自动调整字体大小,确保文本在各种设备上都易于阅读。</p>
<a href="#" class="btn">了解更多</a>
</div>
<div class="card">
<h2 class="card-title">网格布局</h2>
<p class="card-text">使用 CSS Grid 和 CSS 变量创建灵活的网格布局,根据屏幕尺寸自动调整列数和间距,实现响应式的卡片排列。</p>
<a href="#" class="btn">了解更多</a>
</div>
<div class="card">
<h2 class="card-title">移动设备优化</h2>
<p class="card-text">针对移动设备优化导航菜单和内容布局,提供更好的触摸体验和页面性能。</p>
<a href="#" class="btn">了解更多</a>
</div>
<div class="card">
<h2 class="card-title">性能优化</h2>
<p class="card-text">通过合理使用 CSS 变量和媒体查询,减少 CSS 代码量,提高页面加载速度和渲染性能。</p>
<a href="#" class="btn">了解更多</a>
</div>
</div>
</div>
</section>
<footer>
<div class="container">
<p>© 2026 My Website. 保留所有权利。</p>
</div>
</footer>
<script>
const mobileMenuBtn = document.getElementById('mobileMenuBtn');
const navMenu = document.getElementById('navMenu');
mobileMenuBtn.addEventListener('click', () => {
navMenu.classList.toggle('active');
});
</script>
</body>
</html>效果: 网页会根据屏幕尺寸自动调整布局和样式,在不同设备上都能提供良好的用户体验。
3.3 动画控制
场景: 使用 CSS 变量控制动画参数,实现更加灵活和可维护的动画效果。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动画控制示例</title>
<style>
/* 定义动画变量 */
:root {
--animation-duration: 2s;
--animation-timing-function: ease-in-out;
--animation-iteration-count: infinite;
--animation-delay: 0s;
--animation-direction: alternate;
--animation-fill-mode: both;
--primary-color: #3498db;
--secondary-color: #e74c3c;
--animation-distance: 100px;
--animation-scale: 1.2;
--animation-rotation: 180deg;
--animation-opacity: 0.5;
}
/* 全局样式 */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
background-color: #f5f5f5;
color: #333;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
}
h1 {
text-align: center;
margin-bottom: 40px;
color: var(--primary-color);
}
.animation-container {
display: flex;
flex-wrap: wrap;
gap: 30px;
justify-content: center;
align-items: center;
margin-bottom: 40px;
}
.animation-item {
width: 200px;
height: 200px;
background-color: var(--primary-color);
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 18px;
font-weight: bold;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
/* 平移动画 */
.translate-animation {
animation: translateAnimation var(--animation-duration) var(--animation-timing-function) var(--animation-iteration-count) var(--animation-delay) var(--animation-direction) var(--animation-fill-mode);
}
@keyframes translateAnimation {
0% {
transform: translateX(0);
}
100% {
transform: translateX(var(--animation-distance));
}
}
/* 缩放动画 */
.scale-animation {
animation: scaleAnimation var(--animation-duration) var(--animation-timing-function) var(--animation-iteration-count) var(--animation-delay) var(--animation-direction) var(--animation-fill-mode);
}
@keyframes scaleAnimation {
0% {
transform: scale(1);
}
100% {
transform: scale(var(--animation-scale));
}
}
/* 旋转动画 */
.rotate-animation {
animation: rotateAnimation var(--animation-duration) var(--animation-timing-function) var(--animation-iteration-count) var(--animation-delay) var(--animation-direction) var(--animation-fill-mode);
}
@keyframes rotateAnimation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(var(--animation-rotation));
}
}
/* 透明度动画 */
.opacity-animation {
animation: opacityAnimation var(--animation-duration) var(--animation-timing-function) var(--animation-iteration-count) var(--animation-delay) var(--animation-direction) var(--animation-fill-mode);
}
@keyframes opacityAnimation {
0% {
opacity: 1;
}
100% {
opacity: var(--animation-opacity);
}
}
/* 颜色动画 */
.color-animation {
animation: colorAnimation var(--animation-duration) var(--animation-timing-function) var(--animation-iteration-count) var(--animation-delay) var(--animation-direction) var(--animation-fill-mode);
}
@keyframes colorAnimation {
0% {
background-color: var(--primary-color);
}
100% {
background-color: var(--secondary-color);
}
}
/* 控制面板 */
.control-panel {
background-color: white;
border-radius: 8px;
padding: 30px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.control-group {
margin-bottom: 20px;
}
.control-label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: #555;
}
.control-input {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
.control-range {
width: 100%;
}
.control-value {
display: inline-block;
margin-left: 10px;
font-size: 14px;
color: #777;
min-width: 60px;
}
.control-buttons {
display: flex;
gap: 10px;
margin-top: 30px;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 4px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.3s;
}
.btn-primary {
background-color: var(--primary-color);
color: white;
}
.btn-primary:hover {
background-color: #2980b9;
}
.btn-secondary {
background-color: #95a5a6;
color: white;
}
.btn-secondary:hover {
background-color: #7f8c8d;
}
@media (max-width: 768px) {
.animation-container {
flex-direction: column;
}
.control-buttons {
flex-direction: column;
}
}
</style>
</head>
<body>
<div class="container">
<h1>CSS 变量动画控制示例</h1>
<div class="animation-container">
<div class="animation-item translate-animation">平移动画</div>
<div class="animation-item scale-animation">缩放动画</div>
<div class="animation-item rotate-animation">旋转动画</div>
<div class="animation-item opacity-animation">透明度动画</div>
<div class="animation-item color-animation">颜色动画</div>
</div>
<div class="control-panel">
<h2 style="margin-bottom: 20px;">动画控制面板</h2>
<div class="control-group">
<label class="control-label" for="duration">动画持续时间 (秒)</label>
<input type="range" class="control-range" id="duration" min="0.1" max="5" step="0.1" value="2">
<span class="control-value" id="durationValue">2</span>
</div>
<div class="control-group">
<label class="control-label" for="distance">平移距离 (px)</label>
<input type="range" class="control-range" id="distance" min="10" max="300" step="10" value="100">
<span class="control-value" id="distanceValue">100</span>
</div>
<div class="control-group">
<label class="control-label" for="scale">缩放比例</label>
<input type="range" class="control-range" id="scale" min="0.1" max="2" step="0.1" value="1.2">
<span class="control-value" id="scaleValue">1.2</span>
</div>
<div class="control-group">
<label class="control-label" for="rotation">旋转角度 (度)</label>
<input type="range" class="control-range" id="rotation" min="0" max="360" step="15" value="180">
<span class="control-value" id="rotationValue">180</span>
</div>
<div class="control-group">
<label class="control-label" for="opacity">透明度</label>
<input type="range" class="control-range" id="opacity" min="0" max="1" step="0.1" value="0.5">
<span class="control-value" id="opacityValue">0.5</span>
</div>
<div class="control-buttons">
<button class="btn btn-primary" id="resetBtn">重置动画</button>
<button class="btn btn-secondary" id="randomBtn">随机参数</button>
</div>
</div>
</div>
<script>
const root = document.documentElement;
const durationSlider = document.getElementById('duration');
const durationValue = document.getElementById('durationValue');
const distanceSlider = document.getElementById('distance');
const distanceValue = document.getElementById('distanceValue');
const scaleSlider = document.getElementById('scale');
const scaleValue = document.getElementById('scaleValue');
const rotationSlider = document.getElementById('rotation');
const rotationValue = document.getElementById('rotationValue');
const opacitySlider = document.getElementById('opacity');
const opacityValue = document.getElementById('opacityValue');
const resetBtn = document.getElementById('resetBtn');
const randomBtn = document.getElementById('randomBtn');
const animationItems = document.querySelectorAll('.animation-item');
// 更新持续时间
durationSlider.addEventListener('input', () => {
const value = durationSlider.value;
durationValue.textContent = value;
root.style.setProperty('--animation-duration', `${value}s`);
});
// 更新平移距离
distanceSlider.addEventListener('input', () => {
const value = distanceSlider.value;
distanceValue.textContent = value;
root.style.setProperty('--animation-distance', `${value}px`);
});
// 更新缩放比例
scaleSlider.addEventListener('input', () => {
const value = scaleSlider.value;
scaleValue.textContent = value;
root.style.setProperty('--animation-scale', value);
});
// 更新旋转角度
rotationSlider.addEventListener('input', () => {
const value = rotationSlider.value;
rotationValue.textContent = value;
root.style.setProperty('--animation-rotation', `${value}deg`);
});
// 更新透明度
opacitySlider.addEventListener('input', () => {
const value = opacitySlider.value;
opacityValue.textContent = value;
root.style.setProperty('--animation-opacity', value);
});
// 重置动画
resetBtn.addEventListener('click', () => {
durationSlider.value = 2;
durationValue.textContent = '2';
distanceSlider.value = 100;
distanceValue.textContent = '100';
scaleSlider.value = 1.2;
scaleValue.textContent = '1.2';
rotationSlider.value = 180;
rotationValue.textContent = '180';
opacitySlider.value = 0.5;
opacityValue.textContent = '0.5';
root.style.setProperty('--animation-duration', '2s');
root.style.setProperty('--animation-distance', '100px');
root.style.setProperty('--animation-scale', '1.2');
root.style.setProperty('--animation-rotation', '180deg');
root.style.setProperty('--animation-opacity', '0.5');
});
// 随机参数
randomBtn.addEventListener('click', () => {
const randomDuration = (Math.random() * 4 + 0.5).toFixed(1);
const randomDistance = Math.floor(Math.random() * 200 + 50);
const randomScale = (Math.random() * 1 + 0.5).toFixed(1);
const randomRotation = Math.floor(Math.random() * 360);
const randomOpacity = (Math.random() * 0.8 + 0.2).toFixed(1);
durationSlider.value = randomDuration;
durationValue.textContent = randomDuration;
distanceSlider.value = randomDistance;
distanceValue.textContent = randomDistance;
scaleSlider.value = randomScale;
scaleValue.textContent = randomScale;
rotationSlider.value = randomRotation;
rotationValue.textContent = randomRotation;
opacitySlider.value = randomOpacity;
opacityValue.textContent = randomOpacity;
root.style.setProperty('--animation-duration', `${randomDuration}s`);
root.style.setProperty('--animation-distance', `${randomDistance}px`);
root.style.setProperty('--animation-scale', randomScale);
root.style.setProperty('--animation-rotation', `${randomRotation}deg`);
root.style.setProperty('--animation-opacity', randomOpacity);
});
</script>
</body>
</html>效果: 网页显示五个具有不同动画效果的元素,用户可以通过控制面板调整动画参数,实时预览动画效果。
4. 浏览器兼容性
| 浏览器 | 支持情况 |
|---|---|
| Chrome | ✅ 支持 (49+) |
| Firefox | ✅ 支持 (31+) |
| Safari | ✅ 支持 (9.1+) |
| Edge | ✅ 支持 (15+) |
| IE | ❌ 不支持 |
5. 最佳实践
使用语义化的变量名:选择描述性的变量名,使代码更加易于理解和维护。
/* 好的变量名 */ :root { --primary-color: #3498db; --font-size-base: 16px; --spacing-unit: 8px; } /* 不好的变量名 */ :root { --color1: #3498db; --fs: 16px; --sp: 8px; }在 :root 中定义全局变量:对于需要在整个文档中使用的变量,在
:root伪类中定义,使其成为全局变量。使用局部变量:对于只在特定组件中使用的变量,在组件的选择器中定义,限制其作用域。
使用变量组织主题:使用变量组织颜色、字体、间距等主题相关的样式,便于主题切换和维护。
与 calc() 结合使用:使用变量与
calc()函数结合,实现动态计算值,如响应式尺寸。使用默认值:在使用变量时提供默认值,确保在变量未定义时也能正常显示。
.element { color: var(--primary-color, blue); }避免过度使用:不要为每个值都创建变量,只对需要重用或可能变化的值使用变量。
使用 CSS 变量进行动画控制:使用变量控制动画参数,实现更加灵活和可维护的动画效果。
结合 JavaScript 使用:通过 JavaScript 动态修改变量值,实现交互式的样式变化。
测试兼容性:由于 IE 不支持 CSS 变量,在需要支持 IE 的项目中,需要提供降级方案。
6. 总结
CSS 变量是 CSS3 中引入的一项强大功能,它为我们提供了一种灵活、可维护的方式来管理样式值。通过使用 CSS 变量,我们可以:
减少代码重复:定义一次变量,在多处使用,减少代码冗余。
提高可维护性:通过修改变量值,可以同时更新所有使用该变量的地方,减少维护成本。
实现主题切换:通过修改变量值,可以轻松实现亮色/暗色主题切换等功能。
创建响应式设计:结合媒体查询,使用变量定义响应式参数,实现更加灵活的响应式设计。
控制动画效果:使用变量控制动画参数,实现更加灵活和可维护的动画效果。
与 JavaScript 交互:通过 JavaScript 动态修改变量值,实现交互式的样式变化。
随着浏览器对 CSS 变量支持的不断完善,CSS 变量已经成为现代前端开发中不可或缺的一部分。掌握 CSS 变量的使用方法和高级特性,将使你能够更加高效地编写和维护 CSS 代码,提升前端开发的能力和水平。