CSS 变量 14

119 阅读4分钟

CSS 变量 (CSS Custom Properties) ,也常被称为 CSS 自定义属性

核心概念

CSS 变量是一种允许开发者自定义属性名称并为其赋值的机制。这些自定义的属性(变量)可以在 CSS 文件中的任何地方被引用和重用。这极大地增强了 CSS 的可维护性、可重用性和动态性

为什么需要 CSS 变量?

在 CSS 变量出现之前,如果你想在多个地方使用同一个颜色或尺寸,你通常需要:

  1. 重复书写: 在每个需要的地方都写上相同的值 (例如 #ff6600)。这导致修改困难,容易出错。
  2. 使用 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 开发中非常有用的一个特性,值得掌握和应用。