CSS 变量
本教程共 44 篇 · 第 42 篇 · 更新于 2026-07-29 · 约 12 分钟阅读
42. CSS 变量
本节目标:理解 CSS 变量的概念,能够声明和使用变量,掌握作用域规则和变量覆盖,了解在媒体查询和 JavaScript 中操作变量的方法。
CSS 变量(自定义属性)让你把值存起来重复使用。改一处,所有用到的地方都跟着变。
声明变量
变量名以 -- 开头,赋值方式和普通属性一样:
:root {
--main-color: #3498DB;
--spacing: 16px;
--font-stack: "Helvetica", sans-serif;
}
:root 选择器匹配文档的根元素(<html>)。在这里声明的变量就是全局变量,任何地方都能用。
变量名区分大小写。
和
--main-color是两个不同的变量。
var() 函数
用 var() 函数读取变量的值:
.button {
background-color: var(--main-color);
padding: var(--spacing);
font-family: var(--font-stack);
}
完整示例:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
:root {
--primary: #3498DB;
--bg: #F5F5F5;
--padding: 16px;
}
body {
background: var(--bg);
font-family: sans-serif;
padding: var(--padding);
}
h1 { color: var(--primary); }
.card {
background: white;
border-left: 4px solid var(--primary);
padding: var(--padding);
margin-bottom: var(--padding);
}
</style>
</head>
<body>
<h1>CSS 变量示例</h1>
<div class="card">卡片 1</div>
<div class="card">卡片 2</div>
</body>
</html>
回退值
var() 第二个参数是回退值。变量未定义时,使用回退值:
color: var(--text-color, #333);
background: var(--bg-color, white);
还可以嵌套使用:
color: var(--primary, var(--fallback, #333));
回退值在组件开发中特别有用。组件定义默认值,使用时通过变量覆盖,不需要的值就用默认的。
作用域
变量有作用域,和普通编程语言类似:
全局变量:在 :root 中声明,整个文档可用。
局部变量:在某个选择器内声明,只在该选择器及其子元素中可用。
/* 全局变量 */
:root {
--color: blue;
}
/* 局部变量 */
.alert {
--color: red;
}
/* 这里 --color 是红色 */
.alert { color: var(--color); }
/* 这里 --color 是蓝色 */
.normal { color: var(--color); }
<!DOCTYPE html>
<html lang="zh">
<head>
<style>
:root { --color: blue; }
.alert { --color: red; }
.alert { color: var(--color); }
.normal { color: var(--color); }
</style>
</head>
<body>
<p class="normal">蓝色文字(全局变量)</p>
<p class="alert">红色文字(局部变量覆盖)</p>
</body>
</html>
变量覆盖
局部变量会覆盖同名的全局变量。利用这个特性,可以轻松实现主题切换:
:root {
--bg: white;
--text: #333;
--primary: #3498DB;
}
/* 深色主题 */
.dark {
--bg: #1a1a2e;
--text: #eee;
--primary: #00D2FF;
}
.themed {
background: var(--bg);
color: var(--text);
}
.themed h1 {
color: var(--primary);
}
<!DOCTYPE html>
<html lang="zh">
<head>
<style>
:root {
--bg: white;
--text: #333;
--primary: #3498DB;
}
.dark {
--bg: #1a1a2e;
--text: #eee;
--primary: #00D2FF;
}
.themed {
background: var(--bg);
color: var(--text);
padding: 20px;
transition: all 0.3s;
}
.themed h1 { color: var(--primary); }
</style>
</head>
<body>
<div class="themed" id="content">
<h1>主题切换演示</h1>
<p>点击按钮切换主题</p>
</div>
<button onclick="document.getElementById('content').classList.toggle('dark')">切换主题</button>
</body>
</html>
变量覆盖是 CSS 主题切换的核心原理。给
加一个类名,所有变量跟着变,整个页面换肤。
在媒体查询中使用变量
变量配合媒体查询,能大幅简化响应式代码:
:root {
--columns: 1;
--font-size: 14px;
--spacing: 8px;
}
@media (min-width: 768px) {
:root {
--columns: 2;
--font-size: 16px;
--spacing: 16px;
}
}
@media (min-width: 1024px) {
:root {
--columns: 3;
--font-size: 18px;
--spacing: 24px;
}
}
.grid {
display: grid;
grid-template-columns: repeat(var(--columns), 1fr);
gap: var(--spacing);
font-size: var(--font-size);
}
<!DOCTYPE html>
<html lang="zh">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
:root {
--columns: 1;
--font-size: 14px;
--spacing: 8px;
}
@media (min-width: 768px) {
:root {
--columns: 2;
--font-size: 16px;
--spacing: 16px;
}
}
@media (min-width: 1024px) {
:root {
--columns: 3;
--font-size: 18px;
--spacing: 24px;
}
}
.grid {
display: grid;
grid-template-columns: repeat(var(--columns), 1fr);
gap: var(--spacing);
font-size: var(--font-size);
padding: var(--spacing);
}
.item {
background: #3498DB;
color: white;
padding: 20px;
border-radius: 8px;
text-align: center;
}
</style>
</head>
<body>
<div class="grid">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
</body>
</html>
在 JavaScript 中操作变量
CSS 变量可以访问 DOM,所以能用 JavaScript 动态修改:
// 获取根元素
const root = document.documentElement;
// 读取变量
const primary = getComputedStyle(root).getPropertyValue('--primary');
console.log(primary); // 输出: #3498DB
// 设置变量
root.style.setProperty('--primary', '#E74C3C');
<!DOCTYPE html>
<html lang="zh">
<head>
<style>
:root { --primary: #3498DB; }
.box {
width: 100px;
height: 100px;
background: var(--primary);
margin: 20px;
border-radius: 8px;
}
</style>
</head>
<body>
<div class="box"></div>
<button onclick="changeColor()">换色</button>
<script>
function changeColor() {
const colors = ['#3498DB', '#E74C3C', '#2ECC71', '#9B59B6', '#F39C12'];
const random = colors[Math.floor(Math.random() * colors.length)];
document.documentElement.style.setProperty('--primary', random);
}
</script>
</body>
</html>
用
设置的变量值会作为内联样式,优先级较高。如果需要覆盖,记得用
!important或提高选择器特异性。
@property:高级变量定义
CSS 的 @property 规则可以给变量添加类型检查和默认值:
@property --my-color {
syntax: "<color>"; /* 类型:颜色 */
inherits: true; /* 可继承 */
initial-value: gray; /* 默认值 */
}
| 参数 | 说明 |
|---|---|
syntax | 数据类型:<color>、<length>、<number>、<percentage> 等 |
inherits | 是否可继承:true 或 false |
initial-value | 默认值 |
@property --gradient-start {
syntax: "<color>";
inherits: false;
initial-value: #EADEDB;
}
@property --gradient-end {
syntax: "<color>";
inherits: false;
initial-value: #BC70A4;
}
.hero {
background: linear-gradient(var(--gradient-start), var(--gradient-end));
}
Tip是较新的特性(Chrome 85+、Safari 16.4+、Firefox 128+)。生产环境使用前请确认浏览器兼容性。
变量 vs 预处理器
| 特性 | CSS 变量 | Sass/Less 变量 |
|---|---|---|
| 运行时 | 可以动态修改 | 编译后固定 |
| 作用域 | 有(DOM 树决定) | 有(代码块决定) |
| 媒体查询 | 可以 | 不可以 |
| JavaScript | 可以读写 | 不可以 |
| 兼容性 | IE 不支持 | 都支持(编译后) |
CSS 变量的最大优势是动态性。预处理器变量编译后就没了,CSS 变量在浏览器里活着,随时可以改。
变量速查
| 概念 | 说明 |
|---|---|
--name | 变量声明,以双横线开头 |
var(--name) | 读取变量值 |
var(--name, fallback) | 带回退值的读取 |
:root | 全局作用域 |
| 选择器内声明 | 局部作用域 |
setProperty() | JavaScript 设置变量 |
@property | 类型检查和默认值定义 |
变量命名要有语义。
比
--blue更好,因为主题色变了变量名不用改。--spacing-lg比--space2更好理解。