CSS变量与预处理器

CSS变量与预处理器

CSS变量(自定义属性)和预处理器是现代CSS开发的重要工具,它们提供了变量、嵌套、混合宏等功能,大大提高了CSS的可维护性和开发效率。本文将深入讲解CSS变量和预处理器的核心概念、使用方法和最佳实践。

参考资料


一、CSS变量(自定义属性)

1.1 什么是CSS变量

CSS变量(CSS Custom Properties)是CSS中定义可重用值的特性。它们以 -- 开头,通过 var() 函数使用。

1.2 基本语法

定义变量

css 复制代码
/* 在:root中定义全局变量 */
:root {
  --primary-color: #007bff;
  --secondary-color: #6c757d;
  --font-size-base: 16px;
  --spacing-unit: 8px;
}

/* 在特定选择器中定义局部变量 */
.card {
  --card-bg: white;
  --card-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

使用变量

css 复制代码
.button {
  background-color: var(--primary-color);
  font-size: var(--font-size-base);
  padding: var(--spacing-unit) calc(var(--spacing-unit) * 2);
}

.card {
  background-color: var(--card-bg);
  box-shadow: var(--card-shadow);
}

1.3 变量作用域

css 复制代码
/* 全局变量 */
:root {
  --global-color: red;
}

/* 局部变量 */
.container {
  --local-color: blue;
}

/* 使用变量 */
.box {
  color: var(--local-color, var(--global-color)); /* 优先使用局部变量 */
}

1.4 变量默认值

css 复制代码
.box {
  /* 使用默认值 */
  color: var(--primary-color, #007bff);
  
  /* 嵌套默认值 */
  background-color: var(--bg-color, var(--default-bg, white));
}

1.5 动态修改变量

JavaScript修改

javascript 复制代码
// 修改CSS变量
document.documentElement.style.setProperty('--primary-color', '#ff0000');

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

媒体查询中修改

css 复制代码
:root {
  --font-size: 16px;
}

@media (max-width: 767px) {
  :root {
    --font-size: 14px;
  }
}

二、CSS变量实战

2.1 主题切换

css 复制代码
/* 默认主题(浅色) */
:root {
  --bg-color: #ffffff;
  --text-color: #333333;
  --primary-color: #007bff;
  --border-color: #dddddd;
}

/* 深色主题 */
[data-theme="dark"] {
  --bg-color: #1a1a1a;
  --text-color: #ffffff;
  --primary-color: #4dabf7;
  --border-color: #444444;
}

/* 使用变量 */
body {
  background-color: var(--bg-color);
  color: var(--text-color);
}

.button {
  background-color: var(--primary-color);
  border: 1px solid var(--border-color);
}
javascript 复制代码
// 主题切换
function toggleTheme() {
  const currentTheme = document.documentElement.getAttribute('data-theme');
  const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
  document.documentElement.setAttribute('data-theme', newTheme);
}

2.2 响应式设计

css 复制代码
:root {
  --spacing: 20px;
  --font-size: 16px;
  --container-width: 1200px;
}

@media (max-width: 767px) {
  :root {
    --spacing: 10px;
    --font-size: 14px;
    --container-width: 100%;
  }
}

.container {
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 var(--spacing);
}

2.3 组件样式

css 复制代码
/* 按钮组件 */
.button {
  --button-bg: var(--primary-color);
  --button-text: white;
  --button-padding: 12px 24px;
  --button-radius: 4px;
  
  background-color: var(--button-bg);
  color: var(--button-text);
  padding: var(--button-padding);
  border-radius: var(--button-radius);
  border: none;
  cursor: pointer;
}

/* 按钮变体 */
.button--secondary {
  --button-bg: var(--secondary-color);
}

.button--danger {
  --button-bg: #dc3545;
}

.button--small {
  --button-padding: 8px 16px;
  --button-radius: 2px;
}

2.4 网格系统

css 复制代码
:root {
  --grid-columns: 12;
  --grid-gutter: 20px;
}

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

.col-1 { grid-column: span 1; }
.col-2 { grid-column: span 2; }
.col-3 { grid-column: span 3; }
/* ... */
.col-12 { grid-column: span 12; }

@media (max-width: 767px) {
  .col-sm-12 { grid-column: span 12; }
}

三、Sass预处理器

3.1 什么是Sass

Sass(Syntactically Awesome Style Sheets)是一个CSS预处理器,它扩展了CSS的功能,提供了变量、嵌套、混合宏、函数等特性。

3.2 Sass安装

bash 复制代码
# 使用npm安装
npm install -g sass

# 或者使用yarn
yarn global add sass

3.3 Sass编译

bash 复制代码
# 编译单个文件
sass input.scss output.css

# 监听文件变化
sass --watch input.scss:output.css

# 编译整个目录
sass --watch scss:css

3.4 Sass变量

scss 复制代码
// 变量定义
$primary-color: #007bff;
$secondary-color: #6c757d;
$font-size-base: 16px;
$spacing-unit: 8px;

// 变量使用
.button {
  background-color: $primary-color;
  font-size: $font-size-base;
  padding: $spacing-unit * 2;
}

// 变量作用域
.container {
  $local-var: 10px;
  padding: $local-var;
}

// 默认变量
$primary-color: #007bff !default;

3.5 Sass嵌套

scss 复制代码
// 选择器嵌套
.nav {
  background-color: #333;
  
  .nav-item {
    display: inline-block;
    
    .nav-link {
      color: white;
      text-decoration: none;
      
      &:hover {
        color: #ddd;
      }
      
      &.active {
        color: #007bff;
      }
    }
  }
}

// 属性嵌合
.box {
  font: {
    family: Arial, sans-serif;
    size: 16px;
    weight: bold;
  }
  
  border: {
    width: 1px;
    style: solid;
    color: #ddd;
  }
}

3.6 Sass混合宏(Mixins)

scss 复制代码
// 定义混合宏
@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

@mixin flex-between {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

// 带参数的混合宏
@mixin button-style($bg-color, $text-color: white) {
  background-color: $bg-color;
  color: $text-color;
  padding: 12px 24px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  
  &:hover {
    opacity: 0.9;
  }
}

// 使用混合宏
.container {
  @include flex-center;
}

.button {
  @include button-style(#007bff);
}

.button--danger {
  @include button-style(#dc3545);
}

3.7 Sass函数

scss 复制代码
// 自定义函数
@function calculate-rem($px, $base: 16px) {
  @return $px / $base * 1rem;
}

// 使用函数
.box {
  font-size: calculate-rem(18px);
  padding: calculate-rem(20px);
}

// 内置函数
$color: #007bff;

.lighter {
  color: lighten($color, 20%);
}

.darker {
  color: darken($color, 20%);
}

.transparent {
  color: transparentize($color, 0.5);
}

3.8 Sass继承

scss 复制代码
// 定义基础样式
%base-button {
  padding: 12px 24px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
}

// 继承基础样式
.button {
  @extend %base-button;
  background-color: #007bff;
  color: white;
}

.button--danger {
  @extend %base-button;
  background-color: #dc3545;
  color: white;
}

四、Less预处理器

4.1 什么是Less

Less(Leaner Style Sheets)是另一个CSS预处理器,它扩展了CSS的动态行为,如变量、混合宏、函数等。

4.2 Less安装

bash 复制代码
# 使用npm安装
npm install -g less

# 或者使用yarn
yarn global add less

4.3 Less编译

bash 复制代码
# 编译单个文件
lessc input.less output.css

# 压缩输出
lessc input.less output.css --clean-css

4.4 Less变量

less 复制代码
// 变量定义
@primary-color: #007bff;
@secondary-color: #6c757d;
@font-size-base: 16px;
@spacing-unit: 8px;

// 变量使用
.button {
  background-color: @primary-color;
  font-size: @font-size-base;
  padding: @spacing-unit * 2;
}

// 变量插值
@selector: box;

.@{selector} {
  width: 100px;
}

4.5 Less混合宏

less 复制代码
// 定义混合宏
.flex-center() {
  display: flex;
  justify-content: center;
  align-items: center;
}

.flex-between() {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

// 带参数的混合宏
.button-style(@bg-color, @text-color: white) {
  background-color: @bg-color;
  color: @text-color;
  padding: 12px 24px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  
  &:hover {
    opacity: 0.9;
  }
}

// 使用混合宏
.container {
  .flex-center();
}

.button {
  .button-style(#007bff);
}

.button--danger {
  .button-style(#dc3545);
}

4.6 Less函数

less 复制代码
// 自定义函数
.calculate-rem(@px, @base: 16px) {
  @result: @px / @base * 1rem;
}

// 使用函数
.box {
  .calculate-rem(18px);
  font-size: @result;
}

// 内置函数
@color: #007bff;

.lighter {
  color: lighten(@color, 20%);
}

.darker {
  color: darken(@color, 20%);
}

4.7 Less嵌套

less 复制代码
// 选择器嵌套
.nav {
  background-color: #333;
  
  .nav-item {
    display: inline-block;
    
    .nav-link {
      color: white;
      text-decoration: none;
      
      &:hover {
        color: #ddd;
      }
      
      &.active {
        color: #007bff;
      }
    }
  }
}

五、PostCSS

5.1 什么是PostCSS

PostCSS是一个用JavaScript转换CSS的工具,它通过插件系统提供了各种功能,如自动添加浏览器前缀、压缩CSS、使用未来CSS语法等。

5.2 PostCSS安装

bash 复制代码
# 使用npm安装
npm install -g postcss-cli autoprefixer

# 或者使用yarn
yarn global add postcss-cli autoprefixer

5.3 PostCSS配置

javascript 复制代码
// postcss.config.js
module.exports = {
  plugins: [
    require('autoprefixer'),
    require('cssnano')({
      preset: 'default',
    }),
  ],
};

5.4 常用PostCSS插件

Autoprefixer:自动添加浏览器前缀

css 复制代码
/* 输入 */
.box {
  display: flex;
  transform: rotate(10deg);
}

/* 输出 */
.box {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-transform: rotate(10deg);
  transform: rotate(10deg);
}

cssnano:压缩CSS

css 复制代码
/* 输入 */
.box {
  color: #ff0000;
  background-color: #000000;
  margin: 10px 20px 10px 20px;
}

/* 输出 */
.box{color:red;background-color:#000;margin:10px 20px}

postcss-preset-env:使用未来CSS语法

css 复制代码
/* 输入 */
.box {
  color: oklch(40% 0.2 250);
}

/* 输出 */
.box {
  color: rgb(0, 82, 204);
}

六、CSS变量 vs 预处理器

6.1 功能对比

功能 CSS变量 Sass Less
变量
嵌套
混合宏
函数
继承
动态修改
浏览器原生

6.2 使用场景

CSS变量适用场景

  • 需要动态修改样式
  • 运行时主题切换
  • 响应式设计中的断点调整
  • 与JavaScript交互

预处理器适用场景

  • 复杂的CSS结构
  • 需要代码复用
  • 大型项目中的样式管理
  • 需要高级功能(如函数、循环)

6.3 混合使用

scss 复制代码
// Sass变量(编译时)
$primary-color: #007bff;

// CSS变量(运行时)
:root {
  --primary-color: #{$primary-color};
  --font-size: 16px;
}

// 使用Sass混合宏
@mixin button-style($bg-color) {
  background-color: $bg-color;
  color: white;
  padding: 12px 24px;
  border: none;
  border-radius: 4px;
}

// 使用CSS变量
.button {
  @include button-style(var(--primary-color));
  font-size: var(--font-size);
}

七、实战案例

7.1 设计系统变量

scss 复制代码
// _variables.scss

// 颜色系统
$color-primary: #007bff;
$color-secondary: #6c757d;
$color-success: #28a745;
$color-danger: #dc3545;
$color-warning: #ffc107;
$color-info: #17a2b8;

// 字体系统
$font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
$font-size-base: 16px;
$font-size-sm: 14px;
$font-size-lg: 18px;

// 间距系统
$spacing-xs: 4px;
$spacing-sm: 8px;
$spacing-md: 16px;
$spacing-lg: 24px;
$spacing-xl: 32px;

// 断点系统
$breakpoint-sm: 576px;
$breakpoint-md: 768px;
$breakpoint-lg: 992px;
$breakpoint-xl: 1200px;
scss 复制代码
// _mixins.scss

// 响应式断点
@mixin respond-to($breakpoint) {
  @if $breakpoint == 'sm' {
    @media (min-width: $breakpoint-sm) { @content; }
  } @else if $breakpoint == 'md' {
    @media (min-width: $breakpoint-md) { @content; }
  } @else if $breakpoint == 'lg' {
    @media (min-width: $breakpoint-lg) { @content; }
  } @else if $breakpoint == 'xl' {
    @media (min-width: $breakpoint-xl) { @content; }
  }
}

// Flex布局
@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

@mixin flex-between {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

// 文本截断
@mixin text-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

// 清除浮动
@mixin clearfix {
  &::after {
    content: '';
    display: table;
    clear: both;
  }
}

7.2 主题切换系统

scss 复制代码
// _themes.scss

// 浅色主题
:root,
[data-theme="light"] {
  --theme-bg: #ffffff;
  --theme-text: #333333;
  --theme-primary: #007bff;
  --theme-border: #dddddd;
  --theme-shadow: rgba(0, 0, 0, 0.1);
}

// 深色主题
[data-theme="dark"] {
  --theme-bg: #1a1a1a;
  --theme-text: #ffffff;
  --theme-primary: #4dabf7;
  --theme-border: #444444;
  --theme-shadow: rgba(0, 0, 0, 0.3);
}

// 主题变量使用
body {
  background-color: var(--theme-bg);
  color: var(--theme-text);
}

.card {
  background-color: var(--theme-bg);
  border: 1px solid var(--theme-border);
  box-shadow: 0 2px 4px var(--theme-shadow);
}

.button {
  background-color: var(--theme-primary);
}

7.3 组件库变量系统

scss 复制代码
// _components.scss

// 按钮组件
.button {
  // 基础变量
  --button-bg: var(--theme-primary);
  --button-text: white;
  --button-padding: #{$spacing-sm} #{$spacing-md};
  --button-radius: 4px;
  --button-font-size: #{$font-size-base};
  
  // 样式
  background-color: var(--button-bg);
  color: var(--button-text);
  padding: var(--button-padding);
  border-radius: var(--button-radius);
  font-size: var(--button-font-size);
  border: none;
  cursor: pointer;
  
  // 变体
  &--secondary {
    --button-bg: var(--theme-secondary);
  }
  
  &--danger {
    --button-bg: var(--theme-danger);
  }
  
  &--small {
    --button-padding: #{$spacing-xs} #{$spacing-sm};
    --button-font-size: #{$font-size-sm};
  }
  
  &--large {
    --button-padding: #{$spacing-md} #{$spacing-lg};
    --button-font-size: #{$font-size-lg};
  }
}

八、最佳实践总结

8.1 CSS变量最佳实践

css 复制代码
/* 1. 使用:root定义全局变量 */
:root {
  --primary-color: #007bff;
  --spacing-unit: 8px;
}

/* 2. 使用有意义的变量名 */
:root {
  --color-primary: #007bff; /* 颜色 */
  --font-size-base: 16px; /* 字体大小 */
  --spacing-md: 16px; /* 间距 */
}

/* 3. 使用默认值 */
.box {
  color: var(--primary-color, #007bff);
}

/* 4. 避免过度使用变量 */
/* 不推荐 */
.box {
  color: var(--color);
  font-size: var(--size);
  margin: var(--margin);
}

/* 推荐 */
.box {
  color: var(--primary-color);
  font-size: var(--font-size-base);
  margin: var(--spacing-md);
}

8.2 Sass/Less最佳实践

scss 复制代码
// 1. 使用部分文件(partials)
// _variables.scss
// _mixins.scss
// _components.scss

// 2. 使用嵌套但避免过度嵌套
.nav {
  .nav-item {
    .nav-link {
      // 最多3层嵌套
    }
  }
}

// 3. 使用混合宏复用代码
@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

// 4. 使用函数计算值
@function calculate-rem($px) {
  @return $px / 16 * 1rem;
}

8.3 构建工具集成

json 复制代码
// package.json
{
  "scripts": {
    "build:css": "sass src/scss:dist/css --style compressed",
    "watch:css": "sass --watch src/scss:dist/css",
    "prefix:css": "postcss dist/css/*.css --use autoprefixer --dir dist/css",
    "build": "npm run build:css && npm run prefix:css"
  }
}

总结

工具 优点 缺点 适用场景
CSS变量 原生支持、动态修改、运行时更新 功能有限 主题切换、响应式设计
Sass 功能强大、代码复用、成熟生态 需要编译 大型项目、组件库
Less 简单易学、JavaScript集成 功能相对较少 中小型项目
PostCSS 插件丰富、未来语法、性能优化 配置复杂 所有项目

CSS变量和预处理器是现代CSS开发的重要工具。建议根据项目需求选择合适的工具,可以混合使用以获得最佳效果。


九、常见面试题与易错点

9.1 面试题精选

题目1:请解释CSS变量和Sass变量的区别,并说明各自的使用场景。

参考答案

  • CSS变量:运行时变量,可以在JavaScript中动态修改,支持回退值,浏览器原生支持
  • Sass变量:编译时变量,编译后消失,不支持动态修改,需要编译工具
  • 使用场景:CSS变量适合主题切换、响应式设计;Sass变量适合设计系统、代码复用

题目2 :以下代码中,.box 的颜色是什么?

css 复制代码
:root {
  --primary-color: blue;
}

.box {
  --primary-color: red;
  color: var(--primary-color);
}

答案 :红色,因为CSS变量遵循就近原则,.box 中定义的变量会覆盖 :root 中的变量

题目3:什么是CSS预处理器?常见的CSS预处理器有哪些?

参考答案

  • CSS预处理器是一种脚本语言,扩展了CSS的功能,增加了变量、嵌套、混合宏、函数等特性
  • 常见的CSS预处理器:Sass、Less、Stylus
  • 优点:代码复用、模块化、可维护性高
  • 缺点:需要编译、学习成本、调试困难

9.2 易错点总结

易错点 错误示例 正确写法 原因
CSS变量作用域错误 全局变量覆盖局部变量 使用局部变量时在元素上定义 CSS变量遵循就近原则
Sass变量未定义 使用未定义的变量 先定义变量再使用 Sass变量需要先定义
混合宏参数错误 参数类型不匹配 使用默认值 混合宏参数需要正确类型
嵌套层级太深 超过3层嵌套 使用类选择器 深层嵌套影响性能和可读性
忘记编译Sass 直接使用.scss文件 使用编译工具 Sass需要编译成CSS

9.3 调试技巧

Chrome DevTools 调试CSS变量

  1. 打开开发者工具
  2. 选择元素
  3. 在Styles面板查看CSS变量
  4. 可以直接修改CSS变量值
  5. 使用Computed面板查看计算后的值

常用调试命令

javascript 复制代码
// 获取CSS变量值
const root = document.documentElement;
const primaryColor = getComputedStyle(root).getPropertyValue('--primary-color');
console.log(primaryColor);

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

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

十、浏览器兼容性参考

特性 Chrome Firefox Safari Edge IE
CSS变量 49+ 31+ 9.1+ 15+ 不支持
var() 函数 49+ 31+ 9.1+ 15+ 不支持
Sass 需要编译 需要编译 需要编译 需要编译 需要编译
Less 需要编译 需要编译 需要编译 需要编译 需要编译
PostCSS 需要编译 需要编译 需要编译 需要编译 需要编译

兼容性建议

  • 现代项目:优先使用CSS变量,结合Sass/Less进行代码组织
  • 需要兼容IE:使用Sass/Less变量,避免使用CSS变量
  • 使用PostCSS进行CSS转换和优化
相关推荐
晴天161 小时前
Chrome DevTools Protocol(CDP)分享-Day36
前端·chrome·chrome devtools
风骏时光牛马1 小时前
程序员的职场成长:技术之外,更要修炼底层思考力
前端
朱 欢 庆4 小时前
云服务器附件备份到本机内网服务器
运维·服务器·前端·经验分享
支支დ9 小时前
VO by Vercel 前端特定优势:为什么它是构建 AI 应用的新范式
前端·人工智能
香芋芋圆10 小时前
AI 冲击内卷之下,普通前端如何破局?WebGIS—— 低门槛突围赛道
前端·javascript·人工智能·学习·职场发展
INS_KF10 小时前
【编程笔记】成员函数中两个 const 的区别(const Data &getData() const;)
前端·javascript·笔记
宿67411 小时前
vue3-async
前端·javascript·vue.js
YXWik611 小时前
记录前端请求接口在浏览器请求响应的Preview和Response展示的一样的问题
前端
2501_9289962211 小时前
GPT-4o换DeepSeek迁移成本多少?中科热备解析API聚合平台技术账本
前端·数据库·人工智能