CSS变量(Custom Properties)

张玥 2025年9月13日 阅读时间 35分钟
CSS3 变量 前端开发 Web标准
CSS代码示例

CSS变量(也称为CSS自定义属性)是CSS的一项强大功能,它允许开发者在样式表中存储特定值并在整个文档中重复使用它们。 这篇文章将深入探讨CSS变量的工作原理、语法、应用场景以及最佳实践,帮助你掌握这一现代Web开发的关键技术。 无论你是想创建可维护的样式系统,还是实现动态主题切换,CSS变量都能提供强大的解决方案。

什么是CSS变量?

CSS变量(自定义属性)是CSS中用于存储特定值的实体,这些值可以在整个文档中重复使用。它们使用自定义属性标记法(例如:--main-color: black;)来声明,并通过var()函数来使用(例如:color: var(--main-color);)。

/* 声明CSS变量 */
:root {
  --primary-color: #3498db;
  --secondary-color: #2ecc71;
  --font-size: 16px;
  --spacing-unit: 8px;
}

/* 使用CSS变量 */
.button {
  background-color: var(--primary-color);
  color: white;
  padding: var(--spacing-unit) calc(var(--spacing-unit) * 2);
  font-size: var(--font-size);
}

.card {
  border: 1px solid var(--primary-color);
  margin-bottom: calc(var(--spacing-unit) * 3);
}
--primary
--secondary
--spacing
按钮使用 --primary-color
卡片使用 --primary-color 和 --spacing-unit

使用CSS变量的好处:

  • 提高可维护性:只需修改变量值即可全局更新样式
  • 增强可读性:通过有意义的变量名使代码更易理解
  • 实现动态主题:通过JavaScript轻松切换主题
  • 减少重复代码:避免在多个地方重复相同的值
  • 支持级联和继承:变量可以在不同选择器中被覆盖

CSS变量的基本用法

1. 声明变量

CSS变量以两个连字符(--)开头,后跟变量名,然后赋予一个值。最佳实践是在:root伪类中声明全局变量,这样它们可以在整个文档中使用。

/* 在:root中声明全局变量 */
:root {
  --main-bg-color: #f8f9fa;
  --main-text-color: #212529;
  --primary: #007bff;
  --border-radius: 0.25rem;
  --box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
  --font-family: 'Segoe UI', system-ui, sans-serif;
  --transition: all 0.3s ease;
}

/* 在特定选择器中声明局部变量 */
.dark-theme {
  --main-bg-color: #121212;
  --main-text-color: #f8f9fa;
}
:root 中定义的变量

2. 使用变量

使用var()函数来访问CSS变量的值。该函数接受两个参数:变量名和可选的备用值(当变量未定义时使用)。

/* 基本用法 */
body {
  background-color: var(--main-bg-color);
  color: var(--main-text-color);
  font-family: var(--font-family);
}

/* 使用备用值 */
.header {
  background-color: var(--header-bg, #f8f9fa);
  padding: var(--header-padding, 1rem);
}

/* 在calc()中使用变量 */
.container {
  padding: calc(var(--spacing) * 2);
  margin: calc(var(--spacing) / 2);
}

/* 在多个属性中使用相同变量 */
.card {
  border: 1px solid var(--border-color, #dee2e6);
  border-radius: var(--border-radius);
  box-shadow: var(--box-shadow);
  transition: var(--transition);
}
这是一个使用CSS变量的卡片
按钮样式

CSS变量的作用域和继承

CSS变量遵循CSS的级联规则,意味着它们具有作用域,并且可以从父元素继承。这使得我们可以创建具有不同主题的组件。

1. 全局作用域与局部作用域

/* 全局变量 */
:root {
  --global-color: red;
  --global-size: 16px;
}

/* 局部变量 - 只在.container内有效 */
.container {
  --local-color: blue;
  --local-size: 20px;
}

/* 使用变量 */
.element {
  color: var(--global-color); /* 红色 */
  font-size: var(--global-size); /* 16px */
}

.container .element {
  color: var(--local-color); /* 蓝色 */
  font-size: var(--local-size); /* 20px */
}
全局作用域的元素
.container内的元素(局部作用域)

2. 变量继承

/* 父元素定义变量 */
.parent {
  --text-color: green;
  --spacing: 1rem;
}

/* 子元素继承变量 */
.child {
  color: var(--text-color); /* 绿色 */
  padding: var(--spacing); /* 1rem */
}

/* 重写继承的变量 */
.special-child {
  --text-color: purple; /* 重写变量 */
  color: var(--text-color); /* 紫色 */
}

父元素(绿色文本)

子元素(继承绿色文本和间距)

特殊子元素(重写为紫色文本)

使用JavaScript操作CSS变量

CSS变量可以通过JavaScript动态修改,这为实现主题切换、响应式设计和用户自定义样式提供了强大的能力。

1. 获取和修改变量值

// 获取根元素的CSS变量
const root = document.documentElement;
const primaryColor = getComputedStyle(root).getPropertyValue('--primary-color');

// 设置新的变量值
root.style.setProperty('--primary-color', '#6c5ce7');

// 修改特定元素的变量
const element = document.querySelector('.my-element');
element.style.setProperty('--local-size', '24px');

// 移除变量设置(恢复继承的值)
root.style.removeProperty('--primary-color');
主要盒子
次要盒子
强调盒子
当前主题: light

2. 创建主题切换功能

// 定义主题
const themes = {
  light: {
    '--bg-color': '#ffffff',
    '--text-color': '#333333',
    '--primary': '#3498db'
  },
  dark: {
    '--bg-color': '#1a1a1a',
    '--text-color': '#ffffff',
    '--primary': '#2980b9'
  },
  blue: {
    '--bg-color': '#e6f7ff',
    '--text-color': '#003366',
    '--primary': '#0073e6'
  }
};

// 应用主题函数
function applyTheme(themeName) {
  const root = document.documentElement;
  const theme = themes[themeName];
  
  Object.keys(theme).forEach(property => {
    root.style.setProperty(property, theme[property]);
  });
  
  // 保存用户选择
  localStorage.setItem('theme', themeName);
}

// 初始化时应用保存的主题
const savedTheme = localStorage.getItem('theme') || 'light';
applyTheme(savedTheme);

主题切换实现原理:

  1. 定义不同主题的CSS变量值
  2. 使用JavaScript将变量应用到根元素
  3. 保存用户选择到localStorage
  4. 页面加载时恢复用户选择

高级技巧和最佳实践

1. 使用CSS变量创建设计系统

通过系统化地使用CSS变量,可以创建一致且可维护的设计系统。

/* 设计系统基础变量 */
:root {
  /* 颜色系统 */
  --color-primary: #3498db;
  --color-secondary: #2ecc71;
  --color-danger: #e74c3c;
  --color-warning: #f39c12;
  --color-dark: #2c3e50;
  --color-light: #ecf0f1;

  /* 间距系统 */
  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;

  /* 字体系统 */
  --font-size-sm: 0.875rem;
  --font-size-md: 1rem;
  --font-size-lg: 1.25rem;
  --font-size-xl: 1.5rem;
  --font-size-2xl: 2rem;

  /* 阴影系统 */
  --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}

/* 使用设计系统变量 */
.btn {
  padding: var(--space-sm) var(--space-md);
  font-size: var(--font-size-md);
  border-radius: 0.25rem;
  box-shadow: var(--shadow-sm);
}

.btn-primary {
  background-color: var(--color-primary);
  color: white;
}
主要按钮
成功按钮
危险按钮

卡片标题

这是一个使用设计系统变量的卡片

操作
取消

2. 使用CSS变量实现响应式设计

/* 基础变量 */
:root {
  --gutter: 1rem;
  --columns: 4;
  --font-size-base: 16px;
}

/* 中等屏幕 */
@media (min-width: 768px) {
  :root {
    --gutter: 1.5rem;
    --columns: 8;
    --font-size-base: 18px;
  }
}

/* 大屏幕 */
@media (min-width: 1024px) {
  :root {
    --gutter: 2rem;
    --columns: 12;
    --font-size-base: 20px;
  }
}

/* 使用响应式变量 */
.container {
  padding: var(--gutter);
  font-size: var(--font-size-base);
}

.grid {
  display: grid;
  grid-template-columns: repeat(var(--columns), 1fr);
  gap: var(--gutter);
}

响应式断点演示:

当前字体大小: 16px (小屏幕)

常见问题与解决方案

1. 浏览器兼容性

CSS变量在现代浏览器中得到广泛支持,但在旧版浏览器(如IE)中不被支持。可以使用以下策略提供降级方案:

/* 提供降级值 */
.element {
  color: #3498db; /* 降级值 */
  color: var(--primary-color, #3498db); /* 使用变量,备用值为降级值 */
}

/* 使用特性查询检测支持 */
@supports (--css: variables) {
  /* 支持CSS变量的样式 */
  .element {
    background-color: var(--bg-color);
  }
}

@supports not (--css: variables) {
  /* 不支持CSS变量的备用样式 */
  .element {
    background-color: #f8f9fa;
  }
}

浏览器支持情况:

  • Chrome: 49+ ✅
  • Firefox: 31+ ✅
  • Safari: 9.1+ ✅
  • Edge: 16+ ✅
  • IE: 不支持 ❌

2. 性能考虑

虽然CSS变量性能通常很好,但在某些情况下需要注意:

/* 避免过度使用变量 */
/* 不好:每个属性都使用变量 */
.element {
  margin-top: var(--space-1);
  margin-right: var(--space-1);
  margin-bottom: var(--space-1);
  margin-left: var(--space-1);
}

/* 更好:使用简写属性 */
.element {
  margin: var(--space-1);
}

/* 避免在动画中使用大量变量 */
/* 可能性能不佳 */
@keyframes slide {
  from {
    transform: translateX(var(--start-pos));
  }
  to {
    transform: translateX(var(--end-pos));
  }
}

性能优化建议:

  • 合理使用变量,避免过度使用
  • 在动画中谨慎使用CSS变量
  • 使用简写属性减少变量使用
  • 避免在频繁变化的元素上使用大量变量