Skip to content
On this page

CSS 预处理器

CSS 预处理器扩展了 CSS 的功能,提供了变量、嵌套、混合等功能。

概述

CSS 预处理器是一种语言,它扩展了 CSS 的功能并编译成标准 CSS。常见的预处理器包括 Sass/SCSS、Less 和 Stylus。

Sass/SCSS

变量

scss
// 定义变量
$primary-color: #007bff;
$font-size: 16px;
$border-radius: 4px;

// 使用变量
.button {
  background-color: $primary-color;
  font-size: $font-size;
  border-radius: $border-radius;
}

嵌套

scss
// 嵌套选择器
.navbar {
  background-color: #333;
  
  ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }
  
  li {
    display: inline-block;
    
    &:hover {
      background-color: #555;
    }
  }
  
  a {
    display: block;
    padding: 10px;
    text-decoration: none;
    
    &:hover {
      color: $primary-color;
    }
  }
}

混合宏 (Mixins)

scss
// 定义混合宏
@mixin button-style($bg-color, $text-color: white) {
  background-color: $bg-color;
  color: $text-color;
  border: none;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  
  &:hover {
    background-color: darken($bg-color, 10%);
  }
}

// 使用混合宏
.primary-btn {
  @include button-style(#007bff);
}

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

函数

scss
// 定义函数
@function calculate-opacity($color, $alpha) {
  @return rgba($color, $alpha);
}

.element {
  background-color: calculate-opacity(#000, 0.5);
}

扩展/继承

scss
%button-base {
  border: none;
  padding: 10px 20px;
  cursor: pointer;
  border-radius: 4px;
}

.btn-primary {
  @extend %button-base;
  background-color: #007bff;
  color: white;
}

.btn-secondary {
  @extend %button-base;
  background-color: #6c757d;
  color: white;
}

条件语句

scss
@mixin theme-color($theme) {
  @if $theme == dark {
    background-color: #333;
    color: #fff;
  } @else if $theme == light {
    background-color: #fff;
    color: #333;
  } @else {
    background-color: #f8f9fa;
    color: #212529;
  }
}

.card-dark {
  @include theme-color(dark);
}

循环

scss
// for 循环
@for $i from 1 through 4 {
  .col-#{$i} {
    width: percentage($i / 12);
  }
}

// each 循环
$colors: (primary: #007bff, secondary: #6c757d, success: #28a745);

@each $name, $color in $colors {
  .text-#{$name} {
    color: $color;
  }
  
  .bg-#{$name} {
    background-color: $color;
  }
}

Less

变量

less
// 定义变量
@primary-color: #007bff;
@font-size: 16px;

// 使用变量
.element {
  color: @primary-color;
  font-size: @font-size;
}

嵌套

less
.nav {
  background-color: #333;
  
  ul {
    margin: 0;
    padding: 0;
  }
  
  li {
    display: inline-block;
    
    &:hover {
      background-color: #555;
    }
  }
}

混合 (Mixins)

less
// 定义混合
.border-radius(@radius: 5px) {
  border-radius: @radius;
  -webkit-border-radius: @radius;
  -moz-border-radius: @radius;
}

// 使用混合
.button {
  .border-radius(10px);
}

Stylus

变量

stylus
// 变量定义
primary-color = #007bff
font-size = 16px

// 使用变量
element
  color: primary-color
  font-size: font-size

嵌套

stylus
.nav
  background-color: #333
  
  ul
    margin: 0
    padding: 0
  
  li
    display: inline-block
    
    &:hover
      background-color: #555

高级特性

嵌套媒体查询

scss
// 在选择器内嵌套媒体查询
.card {
  padding: 1rem;
  
  @media (min-width: 768px) {
    padding: 2rem;
    display: flex;
  }
  
  @media (min-width: 1024px) {
    padding: 3rem;
  }
}

命名空间和访问器

scss
// 定义命名空间
$theme: (
  colors: (
    primary: #007bff,
    secondary: #6c757d,
    success: #28a745
  ),
  sizes: (
    small: 14px,
    normal: 16px,
    large: 18px
  )
);

// 访问嵌套值
$primary-color: map-get(map-get($theme, colors), primary);
$font-size: map-get(map-get($theme, sizes), normal);

// 或使用函数
@function theme-color($key) {
  @return map-get(map-get($theme, colors), $key);
}

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

列表和映射操作

scss
// 列表操作
$sizes: 10px, 20px, 30px, 40px;

@each $size in $sizes {
  .padding-#{str-slice($size, 1, -3)} {
    padding: $size;
  }
}

// 映射操作
$breakpoints: (
  'xs': 0,
  'sm': 576px,
  'md': 768px,
  'lg': 992px,
  'xl': 1200px
);

@each $name, $value in $breakpoints {
  @if $name != 'xs' {
    .hidden-#{$name}-up {
      @media (min-width: $value) {
        display: none;
      }
    }
  }
}

工具函数

颜色函数

scss
.element {
  // 调整颜色
  background-color: lighten(#000, 20%); // 变亮
  border-color: darken(#fff, 20%); // 变暗
  color: saturate(#f00, 20%); // 增加饱和度
  text-color: desaturate(#f00, 20%); // 降低饱和度
  background: adjust-hue(#f00, 180deg); // 调整色相
  transparent-bg: rgba(#000, 0.5); // 透明度
}

数学函数

scss
.element {
  // 数学运算
  width: calc(100% - 40px);
  margin: 20px / 2; // 计算结果
  font-size: 16px * 1.2; // 计算结果
}

框架和库

Bootstrap 变量定制

scss
// 重写 Bootstrap 变量
$primary: #007bff;
$secondary: #6c757d;
$success: #28a745;
$info: #17a2b8;
$warning: #ffc107;
$danger: #dc3545;
$light: #f8f9fa;
$dark: #343a40;

// 导入 Bootstrap
@import "bootstrap/scss/bootstrap";

自定义组件库

scss
// _variables.scss
$grid-gutter-width: 30px !default;
$container-max-widths: (
  sm: 540px,
  md: 720px,
  lg: 960px,
  xl: 1140px
) !default;

// _mixins.scss
@mixin make-col-ready($gutter: $grid-gutter-width) {
  position: relative;
  width: 100%;
  padding-right: $gutter / 2;
  padding-left: $gutter / 2;
}

// _grid.scss
.container {
  @include make-container();
  @include make-container-max-widths();
}

.row {
  @include make-row();
}

构建工具集成

Webpack 配置

javascript
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          'css-loader',
          'sass-loader'
        ]
      }
    ]
  }
};

Gulp 配置

javascript
// gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));

gulp.task('sass', function() {
  return gulp.src('src/scss/**/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(gulp.dest('dist/css'));
});

gulp.task('watch', function() {
  gulp.watch('src/scss/**/*.scss', gulp.series('sass'));
});

最佳实践

项目结构

scss/
├── abstracts/
│   ├── _variables.scss
│   ├── _mixins.scss
│   └── _functions.scss
├── base/
│   ├── _reset.scss
│   ├── _typography.scss
│   └── _helpers.scss
├── components/
│   ├── _buttons.scss
│   ├── _cards.scss
│   └── _forms.scss
├── layout/
│   ├── _header.scss
│   ├── _navigation.scss
│   └── _footer.scss
├── pages/
│   └── _home.scss
├── themes/
│   └── _dark.scss
└── main.scss

main.scss 文件

scss
// 1. 配置和工具
@import "abstracts/variables";
@import "abstracts/functions";
@import "abstracts/mixins";

// 2. 基础样式
@import "base/reset";
@import "base/typography";
@import "base/helpers";

// 3. 布局组件
@import "layout/header";
@import "layout/navigation";
@import "layout/footer";

// 4. 组件
@import "components/buttons";
@import "components/cards";
@import "components/forms";

// 5. 页面特定样式
@import "pages/home";

// 6. 主题
@import "themes/dark";

性能优化

避免深层嵌套

scss
// 避免:深层嵌套
.nav {
  .item {
    .link {
      .icon {
        // 过深的嵌套
      }
    }
  }
}

// 推荐:扁平化结构
.nav { }
.nav-item { }
.nav-link { }
.nav-icon { }

代码组织

scss
// 使用有意义的命名空间
%button-base { }
.button-primary { }
.button-secondary { }

// 避免过长的类名
.very-long-class-name-that-describes-everything { }

调试技巧

输出调试信息

scss
@debug "Debug info: #{$variable}";

// 条件调试
@if $debug-mode {
  .element {
    outline: 1px solid red;
  }
}

最佳实践总结

  • 使用一致的变量命名约定
  • 合理组织项目结构
  • 避免过度嵌套(建议不超过3层)
  • 重用混合宏和函数
  • 使用语义化的类名
  • 定期清理未使用的代码
  • 使用版本控制管理预处理器文件
  • 文档化自定义混合宏和函数的用法