CSS 变量 (CSS Custom Properties) ,也常被称为 CSS 自定义属性。
核心概念
CSS 变量是一种允许开发者自定义属性名称并为其赋值的机制。这些自定义的属性(变量)可以在 CSS 文件中的任何地方被引用和重用。这极大地增强了 CSS 的可维护性、可重用性和动态性。
为什么需要 CSS 变量?
在 CSS 变量出现之前,如果你想在多个地方使用同一个颜色或尺寸,你通常需要:
- 重复书写: 在每个需要的地方都写上相同的值 (例如 #ff6600)。这导致修改困难,容易出错。
- 使用 CSS 预处理器 (Sass/Less): 预处理器提供了变量功能,但这需要在构建时编译 CSS,运行时无法更改。
CSS 变量解决了这些问题:
- DRY (Don't Repeat Yourself): 只需在一个地方定义值,多处引用。修改时只需改动定义处。
- 语义化: 可以给变量起有意义的名字 (如 --primary-color),提高代码可读性。
- 运行时动态性: 变量的值可以在运行时通过 CSS 规则或 JavaScript 改变,从而动态改变页面样式,无需重新编译。这对于主题切换、响应式调整等非常有用。
- 级联和继承: 变量遵循标准的 CSS 级联和继承规则,可以方便地设置全局默认值并在特定组件中覆盖。
如何使用?
使用 CSS 变量主要涉及两个步骤:
1. 定义变量 (Defining Custom Properties)
-
语法:
- 变量名必须以两个连字符 (--) 开头。
- 变量名是大小写敏感的。
- 变量在选择器内部声明,就像普通 CSS 属性一样。
- 变量的值可以是任何有效的 CSS 声明值(颜色、长度、字符串、URL 等)。
-
最佳实践: 通常将全局变量定义在 :root 伪类选择器中。:root 匹配文档的根元素(通常是 ),在这里定义的变量具有全局作用域,可以被页面上的任何元素访问和继承。
/* 定义全局变量 */
:root {
--main-color: #3498db; /* 主题蓝色 */
--secondary-color: #f1c40f; /* 次要黄色 */
--text-color: #333;
--background-color: #ffffff;
--base-spacing: 10px;
--header-height: 60px;
--box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
--logo-url: url('/img/logo.png');
}
/* 定义局部变量 (仅在 .card 及其后代中生效) */
.card {
--card-padding: calc(var(--base-spacing) * 1.5); /* 变量值可以引用其他变量 */
padding: var(--card-padding);
box-shadow: var(--box-shadow);
}
.card.dark {
/* 在特定情况下覆盖局部变量 */
--card-padding: 25px;
--card-text-color: white; /* 定义新的局部变量 */
background-color: #444;
color: var(--card-text-color);
}
2. 使用变量 (Using Custom Properties)
-
语法: 使用 var() 函数来引用已定义的变量。
-
var() 函数:
- 第一个参数 (必需): 要引用的变量名 (带 --)。
- 第二个参数 (可选): 回退值 (Fallback Value) 。如果第一个参数指定的变量未定义或无效,则使用此回退值。回退值本身也可以是另一个 var() 函数。
body {
background-color: var(--background-color);
color: var(--text-color);
margin-top: var(--header-height); /* 使用 header 高度作为 body 的上边距 */
}
h1 {
color: var(--main-color); /* 标题使用主颜色 */
}
button {
background-color: var(--main-color);
color: white;
padding: var(--base-spacing) calc(var(--base-spacing) * 2); /* 内边距使用基础间距 */
border: none;
border-radius: 4px;
}
button.secondary {
background-color: var(--secondary-color);
color: var(--text-color);
}
.alert {
/* 如果 --alert-color 未定义,则使用红色作为回退 */
border-color: var(--alert-color, red);
padding: var(--base-spacing);
}
.logo {
/* 使用 URL 变量 */
content: var(--logo-url);
}
作用域和继承
- 作用域: 变量的作用域由定义它的选择器决定。定义在 :root 上的变量是全局的。定义在特定类或 ID 上的变量是局部的。
- 继承: CSS 变量是默认继承的。子元素会继承父元素定义的变量值,除非子元素自己重新定义了同名变量。
与 JavaScript 交互
CSS 变量可以很容易地通过 JavaScript 读取和修改,这使得实现动态主题、响应用户交互等非常方便。
-
读取变量:
// 获取 :root 上的全局变量 const rootStyles = getComputedStyle(document.documentElement); const mainColor = rootStyles.getPropertyValue('--main-color').trim(); // .trim() 去空格 console.log(mainColor); // 输出: #3498db (或当前值) // 获取特定元素的变量 (可能继承自父级) const cardElement = document.querySelector('.card'); const cardPadding = getComputedStyle(cardElement).getPropertyValue('--card-padding').trim(); console.log(cardPadding); -
修改变量:
// 修改 :root 上的全局变量 (影响所有继承该变量的元素) document.documentElement.style.setProperty('--main-color', 'darkorange'); document.documentElement.style.setProperty('--background-color', '#222'); // 切换到暗色模式 // 修改特定元素的局部变量 const darkCard = document.querySelector('.card.dark'); darkCard.style.setProperty('--card-padding', '30px');
优点总结:
- 提高可维护性: 修改一处定义,所有引用处生效。
- 增强可读性: 使用有意义的变量名。
- 简化复杂计算: calc() 可以与 var() 结合使用。
- 实现动态主题切换: 通过 JS 修改根变量即可改变全局样式。
- 改善响应式设计: 可以在媒体查询中重新定义变量值。
- 组件化开发: 组件可以定义自己的局部变量,封装样式。
CSS 变量是现代 CSS 开发中非常有用的一个特性,值得掌握和应用。