CSS变量

使用自定义属性创建可维护的样式系统

什么是CSS变量?

CSS变量(也称为自定义属性)是CSS3中的一个重要特性,允许您在样式表中存储值,并在整个文档中重复使用这些值。这大大提高了CSS的可维护性、灵活性和主题化能力。

CSS变量的优势:
  • 提高代码的可维护性
  • 轻松实现主题切换
  • 减少代码重复
  • 支持JavaScript动态修改
  • 提高开发效率
  • 支持响应式设计

浏览器支持

CSS变量在现代浏览器中得到了广泛支持:

Chrome 49.0+
Firefox 31.0+
Safari 9.1+
Edge 15.0+
IE 不支持

定义和使用CSS变量

定义变量

使用两个连字符(--)作为前缀来定义变量:

CSS
:root {
    --primary-color: #82255E;
    --secondary-color: #B83B6A;
    --spacing: 1rem;
    --border-radius: 10px;
    --font-family: "微软雅黑", sans-serif;
    --transition: all 0.3s ease;
}

使用变量

使用var()函数来引用变量:

CSS
.button {
    background-color: var(--primary-color);
    padding: var(--spacing);
    border-radius: var(--border-radius);
    font-family: var(--font-family);
    transition: var(--transition);
}

变量命名规范

为了保持代码的可读性和一致性,建议遵循以下命名规范:

  • 使用有意义的名称
  • 使用kebab-case(短横线分隔)命名法
  • 使用语义化名称而不是具体值
  • 考虑命名空间,特别是对于大型项目
CSS
/* 好的命名 */
:root {
    --color-primary: #82255E;
    --spacing-small: 0.5rem;
    --font-size-heading: 2rem;
}

/* 不好的命名 */
:root {
    --color1: #82255E; /* 没有意义 */
    --smallSpacing: 0.5rem; /* 不使用kebab-case */
}

变量作用域

CSS变量遵循CSS的层叠规则,可以在不同作用域中定义和覆盖:

CSS
/* 全局变量 */
:root {
    --primary-color: blue;
}

/* 组件级变量 */
.component {
    --primary-color: red;
    background-color: var(--primary-color);
    /* 使用红色,而不是蓝色 */
}

/* 元素级变量 */
.special-element {
    --primary-color: green;
}
使用全局变量
使用局部变量(覆盖全局变量)
使用另一个局部变量

作用域继承

CSS变量具有继承性,子元素会继承父元素的变量值:

CSS
.parent {
    --text-color: red;
}

.child {
    color: var(--text-color); /* 继承父元素的 --text-color */
}

回退值

var()函数可以接受一个回退值,当变量未定义时使用:

CSS
.element {
    background-color: var(--custom-color, blue);
    /* 如果--custom-color未定义,使用蓝色 */
    
    padding: var(--spacing, 10px 20px);
    /* 如果--spacing未定义,使用10px 20px */
    
    font-size: var(--font-size, var(--base-font-size, 16px));
    /* 嵌套回退值 */
}
使用回退值(--undefined-color未定义,回退到--secondary-color)
注意: 回退值只在变量未定义时使用。如果变量已定义但值为无效值(如无效的颜色值),回退值不会被使用。

在calc()中使用变量

CSS变量可以与calc()函数结合使用,进行动态计算:

CSS
:root {
    --base-size: 16px;
    --spacing-multiplier: 2;
    --header-height: 60px;
}

.element {
    font-size: calc(var(--base-size) * 1.5);
    margin: calc(var(--base-size) * var(--spacing-multiplier));
    height: calc(100vh - var(--header-height));
}
这个元素的字体大小是24px,外边距是32px

使用JavaScript操作CSS变量

CSS变量可以通过JavaScript动态修改,这使得实时主题切换和动态样式成为可能:

JavaScript
// 获取根元素
const root = document.documentElement;

// 设置变量值
root.style.setProperty('--primary-color', '#ff0000');

// 获取变量值
const primaryColor = getComputedStyle(root)
    .getPropertyValue('--primary-color');

// 移除变量
root.style.removeProperty('--primary-color');

// 批量设置变量
const theme = {
    '--primary-color': '#82255E',
    '--secondary-color': '#B83B6A',
    '--spacing': '1rem'
};

Object.keys(theme).forEach(key => {
    root.style.setProperty(key, theme[key]);
});

响应式变量更新

可以使用JavaScript监听事件并动态更新CSS变量:

JavaScript
// 根据窗口大小更新变量
function updateSpacing() {
    const width = window.innerWidth;
    const spacing = width > 1200 ? '2rem' : width > 768 ? '1.5rem' : '1rem';
    document.documentElement.style.setProperty('--spacing', spacing);
}

// 监听窗口大小变化
window.addEventListener('resize', updateSpacing);
updateSpacing(); // 初始化

CSS变量演示

主题变量

样式变量

当前主题色: #82255E
CSS变量状态: 已应用

CSS变量效果演示

1
主要演示元素
使用: var(--demo-primary)
间距: var(--demo-spacing)
2
次要演示元素
使用: var(--accent-color)
圆角: var(--demo-radius)
3
自定义变量元素
局部变量: #B83B6A
阴影: var(--demo-shadow)

当前CSS变量代码

CSS
:root {
  --demo-primary: #82255E;
  --demo-spacing: 16px;
  --demo-radius: 5px;
  --demo-shadow: 5px;
  --demo-font-size: 16px;
}

实际应用示例

主题切换

CSS
/* 默认主题 */
:root {
    --bg-color: #ffffff;
    --text-color: #333333;
    --primary-color: #82255E;
    --border-color: #e0e0e0;
}

/* 暗色主题 */
.dark-theme {
    --bg-color: #333333;
    --text-color: #ffffff;
    --primary-color: #B83B6A;
    --border-color: #555555;
}

body {
    background-color: var(--bg-color);
    color: var(--text-color);
}

.card {
    background-color: var(--bg-color);
    border: 1px solid var(--border-color);
}

响应式设计

CSS
:root {
    --spacing: 1rem;
    --font-size: 16px;
    --columns: 1;
}

@media (min-width: 768px) {
    :root {
        --spacing: 2rem;
        --font-size: 18px;
        --columns: 2;
    }
}

@media (min-width: 1200px) {
    :root {
        --spacing: 3rem;
        --font-size: 20px;
        --columns: 3;
    }
}

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

组件样式

CSS
.card {
    --card-padding: 1rem;
    --card-radius: 8px;
    --card-shadow: 0 2px 4px rgba(0,0,0,0.1);
    --card-bg: white;
    
    padding: var(--card-padding);
    border-radius: var(--card-radius);
    box-shadow: var(--card-shadow);
    background-color: var(--card-bg);
}

.card.large {
    --card-padding: 2rem;
}

.card.dark {
    --card-bg: #333;
    --card-shadow: 0 2px 4px rgba(0,0,0,0.3);
}

CSS变量与Sass/Less变量对比

CSS变量与预处理器变量有本质区别:

特性 CSS变量 Sass/Less变量
作用域 运行时,遵循CSS层叠 编译时,遵循预处理器作用域规则
动态性 可以通过JavaScript动态修改 编译后固定,无法修改
浏览器支持 现代浏览器支持 所有浏览器(编译为CSS后)
使用场景 主题切换、动态样式 代码复用、计算、混入