Sass、Less 和 SCSS 的区别及用法详解

目录

概述

CSS 预处理器是一种用于扩展 CSS 功能的工具,它们允许开发者使用变量、嵌套、混合、函数等高级特性来编写更加灵活和可维护的样式代码。目前最流行的三种 CSS 预处理器是 SassLessSCSS

CSS 预处理器简介

什么是 CSS 预处理器?

CSS 预处理器是一种脚本语言,它扩展了 CSS 的功能,并将其编译成标准的 CSS 代码。它们提供了以下主要优势:

  • 变量支持:定义可重用的值
  • 嵌套规则:更直观的层级结构
  • 混合(Mixins):可重用的代码块
  • 函数和运算:动态计算样式值
  • 模块化:更好的代码组织
  • 继承:减少代码重复

为什么使用预处理器?

  1. 提高开发效率:减少重复代码编写
  2. 增强可维护性:更好的代码结构和组织
  3. 支持复杂逻辑:条件语句、循环等
  4. 团队协作:统一的代码风格和规范

Sass 详解

Sass 简介

Sass(Syntactically Awesome StyleSheets)是最早的 CSS 预处理器之一,由 Hampton Catlin 于 2006 年创建。Sass 有两种语法格式:

  1. 缩进语法(.sass):使用缩进和换行来定义代码块
  2. SCSS 语法(.scss):类似于 CSS 的语法,使用大括号和分号

Sass 缩进语法特点

// 变量定义
$primary-color: #3498db
$font-size: 16px
$margin: 10px

// 嵌套
.navbar
  background-color: $primary-color
  padding: $margin

  .nav-item
    font-size: $font-size
    color: white

    &:hover
      opacity: 0.8

// 混合
@mixin button-style($bg-color, $text-color)
  background-color: $bg-color
  color: $text-color
  padding: 10px 20px
  border: none
  border-radius: 4px
  cursor: pointer

  &:hover
    opacity: 0.9

// 使用混合
.btn-primary
  @include button-style($primary-color, white)

.btn-secondary
  @include button-style(#95a5a6, white)

Sass 高级特性

1. 控制指令

// 条件语句
@mixin theme-color($theme)
  @if $theme == dark
    background-color: #333
    color: white
  @else if $theme == light
    background-color: white
    color: #333
  @else
    background-color: #f0f0f0
    color: #666

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

// 遍历列表
$colors: red, green, blue, yellow
@each $color in $colors
  .text-#{$color}
    color: $color

2. 函数

// 自定义函数
@function calculate-rem($px)
  @return $px / 16px * 1rem

// 使用函数
.title
  font-size: calculate-rem(24px)
  margin-bottom: calculate-rem(16px)

3. 继承

// 占位符选择器
%button-base
  padding: 10px 15px
  border: none
  border-radius: 4px
  cursor: pointer
  font-size: 14px

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

.btn-danger
  @extend %button-base
  background-color: #dc3545
  color: white

Less 详解

Less 简介

Less(Leaner Style Sheets)是由 Alexis Sellier 于 2009 年创建的 CSS 预处理器。Less 的语法更接近 CSS,学习曲线相对平缓。

Less 基本语法

// 变量定义
@primary-color: #3498db;
@font-size: 16px;
@margin: 10px;

// 嵌套
.navbar {
  background-color: @primary-color;
  padding: @margin;

  .nav-item {
    font-size: @font-size;
    color: white;

    &:hover {
      opacity: 0.8;
    }
  }
}

// 混合
.button-style(@bg-color, @text-color) {
  background-color: @bg-color;
  color: @text-color;
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;

  &:hover {
    opacity: 0.9;
  }
}

// 使用混合
.btn-primary {
  .button-style(@primary-color, white);
}

.btn-secondary {
  .button-style(#95a5a6, white);
}

Less 高级特性

1. 运算

@base-font-size: 14px;
@line-height: 1.5;

.container {
  font-size: @base-font-size;
  line-height: @base-font-size * @line-height;
  margin: (@base-font-size * 2) auto;
  width: 100% - 40px;
}

// 颜色运算
@base-color: #f04124;
.warning {
  color: @base-color;
  background-color: lighten(@base-color, 40%);
  border-color: darken(@base-color, 10%);
}

2. 函数

// 内置函数
.color-functions {
  // 颜色函数
  color: lighten(#000, 50%);           // 变亮
  background: darken(#fff, 20%);       // 变暗
  border-color: saturate(#ccc, 30%);   // 增加饱和度

  // 数学函数
  width: percentage(3/4);              // 75%
  height: round(10.6px);               // 11px
  margin: ceil(10.1px);                // 11px
  padding: floor(10.9px);              // 10px
}

3. 条件语句和循环

// 条件混合
.border-radius(@radius) when (@radius > 0) {
  border-radius: @radius;
}

.border-radius(@radius) when (@radius = 0) {
  border-radius: 0;
}

// 递归实现循环
.generate-columns(@n, @i: 1) when (@i =< @n) {
  .col-@{i} {
    width: percentage(@i / @n);
  }
  .generate-columns(@n, (@i + 1));
}

.generate-columns(12);

4. 命名空间

// 定义命名空间
#bundle {
  .button {
    display: inline-block;
    border: 1px solid black;
    background-color: grey;
    &:hover {
      background-color: white;
    }
  }
  .tab { ... }
  .citation { ... }
}

// 使用命名空间
.my-button {
  #bundle > .button();
}

SCSS 详解

SCSS 简介

SCSS(Sassy CSS)是 Sass 的 CSS 语法版本,它保持了 CSS 的语法结构(使用大括号和分号),同时提供了 Sass 的所有功能。SCSS 是目前最流行的 CSS 预处理器语法。

SCSS 基本语法

// 变量定义
$primary-color: #3498db;
$font-size: 16px;
$margin: 10px;

// 嵌套
.navbar {
  background-color: $primary-color;
  padding: $margin;

  .nav-item {
    font-size: $font-size;
    color: white;

    &:hover {
      opacity: 0.8;
    }
  }
}

// 混合
@mixin button-style($bg-color, $text-color) {
  background-color: $bg-color;
  color: $text-color;
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;

  &:hover {
    opacity: 0.9;
  }
}

// 使用混合
.btn-primary {
  @include button-style($primary-color, white);
}

.btn-secondary {
  @include button-style(#95a5a6, white);
}

SCSS 高级特性

1. 模块系统(Sass 模块)

// _variables.scss
$primary-color: #007bff;
$secondary-color: #6c757d;
$font-family: 'Helvetica Neue', sans-serif;

// _mixins.scss
@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

@mixin responsive($breakpoint) {
  @if $breakpoint == mobile {
    @media (max-width: 767px) { @content; }
  }
  @if $breakpoint == tablet {
    @media (min-width: 768px) and (max-width: 1023px) { @content; }
  }
  @if $breakpoint == desktop {
    @media (min-width: 1024px) { @content; }
  }
}

// main.scss
@use 'variables' as vars;
@use 'mixins';

.header {
  background-color: vars.$primary-color;
  @include mixins.flex-center;

  @include mixins.responsive(mobile) {
    padding: 10px;
  }

  @include mixins.responsive(desktop) {
    padding: 20px;
  }
}

2. 映射(Maps)

// 定义映射
$breakpoints: (
  'small': 576px,
  'medium': 768px,
  'large': 992px,
  'xlarge': 1200px
);

$theme-colors: (
  'primary': #007bff,
  'secondary': #6c757d,
  'success': #28a745,
  'danger': #dc3545,
  'warning': #ffc107,
  'info': #17a2b8
);

// 使用映射
@mixin respond-to($breakpoint) {
  @if map-has-key($breakpoints, $breakpoint) {
    @media (min-width: map-get($breakpoints, $breakpoint)) {
      @content;
    }
  }
}

// 生成主题色类
@each $name, $color in $theme-colors {
  .text-#{$name} {
    color: $color;
  }

  .bg-#{$name} {
    background-color: $color;
  }

  .btn-#{$name} {
    background-color: $color;
    color: white;

    &:hover {
      background-color: darken($color, 10%);
    }
  }
}

3. 内容块(Content Blocks)

@mixin keyframes($name) {
  @-webkit-keyframes #{$name} {
    @content;
  }
  @keyframes #{$name} {
    @content;
  }
}

@include keyframes(slide-in) {
  from {
    transform: translateX(-100%);
  }
  to {
    transform: translateX(0);
  }
}

// 响应式混合
@mixin media-query($device) {
  @if $device == mobile {
    @media only screen and (max-width: 768px) { @content; }
  }
  @if $device == tablet {
    @media only screen and (min-width: 769px) and (max-width: 1024px) { @content; }
  }
  @if $device == desktop {
    @media only screen and (min-width: 1025px) { @content; }
  }
}

.sidebar {
  width: 300px;

  @include media-query(mobile) {
    width: 100%;
    position: fixed;
    top: 0;
    left: -100%;
    transition: left 0.3s ease;

    &.active {
      left: 0;
    }
  }

  @include media-query(tablet) {
    width: 250px;
  }
}

三者对比

语法对比表

特性 Sass Less SCSS
变量 $variable @variable $variable
混合 @mixin name / @include name .name() @mixin name / @include name
嵌套 支持(缩进) 支持(大括号) 支持(大括号)
继承 @extend 不支持 @extend
条件语句 @if / @else when @if / @else
循环 @for / @each / @while 递归 @for / @each / @while
函数 支持 支持 支持
导入 @import / @use @import @import / @use

编译方式对比

Sass/SCSS

  • Ruby Sass:原始实现,已弃用
  • LibSass:C++ 实现,性能更好
  • Dart Sass:官方推荐,功能最完整
# 安装 Dart Sass
npm install -g sass

# 编译单个文件
sass input.scss output.css

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

# 监听目录
sass --watch scss:css

Less

  • Node.js 实现:官方实现
  • 浏览器端编译:开发时可用
# 安装 Less
npm install -g less

# 编译文件
lessc input.less output.css

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

性能对比

预处理器 编译速度 内存占用 文件大小
Sass (Dart) 中等 中等
SCSS (Dart) 中等 中等
Less 中等

语法差异详解

变量定义

// SCSS/Sass
$primary-color: #007bff;
$font-size: 16px;
$is-dark: true;

// Less
@primary-color: #007bff;
@font-size: 16px;
@is-dark: true;

混合(Mixins)

// SCSS
@mixin border-radius($radius: 5px) {
  -webkit-border-radius: $radius;
  -moz-border-radius: $radius;
  border-radius: $radius;
}

.box {
  @include border-radius(10px);
}
// Less
.border-radius(@radius: 5px) {
  -webkit-border-radius: @radius;
  -moz-border-radius: @radius;
  border-radius: @radius;
}

.box {
  .border-radius(10px);
}

条件语句

// SCSS
@mixin theme($theme) {
  @if $theme == dark {
    background: #333;
    color: #fff;
  } @else {
    background: #fff;
    color: #333;
  }
}
// Less
.theme(@theme) when (@theme = dark) {
  background: #333;
  color: #fff;
}

.theme(@theme) when (@theme = light) {
  background: #fff;
  color: #333;
}

循环

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

@each $color in red, green, blue {
  .text-#{$color} {
    color: $color;
  }
}
// Less (递归实现)
.generate-columns(@n, @i: 1) when (@i =< @n) {
  .col-@{i} {
    width: percentage(@i / @n);
  }
  .generate-columns(@n, (@i + 1));
}

.generate-columns(12);

功能特性对比

1. 变量作用域

// SCSS - 块级作用域
$global-var: red;

.component {
  $local-var: blue; // 局部变量
  color: $local-var;

  .nested {
    color: $global-var; // 可以访问全局变量
    // color: $local-var; // 错误:无法访问父级局部变量
  }
}
// Less - 动态作用域
@global-var: red;

.component {
  @local-var: blue;
  color: @local-var;

  .nested {
    color: @global-var; // 可以访问全局变量
    color: @local-var;  // 也可以访问父级变量
  }
}

2. 函数支持

// SCSS - 强大的函数系统
@function calculate-rem($px, $base: 16px) {
  @return $px / $base * 1rem;
}

@function str-replace($string, $search, $replace: '') {
  $index: str-index($string, $search);
  @if $index {
    @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
  }
  @return $string;
}

.title {
  font-size: calculate-rem(24px);
  font-family: str-replace('Helvetica Neue', ' ', '-');
}
// Less - 有限的函数支持
.calculate-rem(@px, @base: 16px) {
  @result: @px / @base * 1rem;
}

.title {
  .calculate-rem(24px);
  font-size: @result;
}

3. 模块系统

// SCSS - 现代模块系统
// _config.scss
$primary-color: #007bff !default;
$secondary-color: #6c757d !default;

// _mixins.scss
@mixin button($bg: $primary-color) {
  background: $bg;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 0.25rem;
}

// main.scss
@use 'config' with (
  $primary-color: #custom-color
);
@use 'mixins';

.btn {
  @include mixins.button(config.$primary-color);
}
// Less - 简单的导入系统
// config.less
@primary-color: #007bff;
@secondary-color: #6c757d;

// mixins.less
.button(@bg: @primary-color) {
  background: @bg;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 0.25rem;
}

// main.less
@import 'config';
@import 'mixins';

.btn {
  .button(@primary-color);
}

生态系统和工具支持

构建工具集成

Webpack 配置

// webpack.config.js
module.exports = {
  module: {
    rules: [
      // SCSS
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              implementation: require('sass'),
              sassOptions: {
                fiber: require('fibers'),
              },
            },
          },
        ],
      },
      // Less
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              lessOptions: {
                javascriptEnabled: true,
              },
            },
          },
        ],
      },
    ],
  },
};

Vite 配置

// vite.config.js
import { defineConfig } from 'vite';

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "@/styles/variables.scss";`,
      },
      less: {
        additionalData: `@import "@/styles/variables.less";`,
        javascriptEnabled: true,
      },
    },
  },
});

IDE 支持

IDE/编辑器 Sass/SCSS Less 插件/扩展
VS Code Sass, Less IntelliSense
WebStorm 内置支持
Sublime Text Sass, LESS
Atom language-sass, language-less

框架集成

Vue.js

<template>
  <div class="component">
    <h1 class="title">Hello World</h1>
  </div>
</template>

<style lang="scss" scoped>
$primary-color: #007bff;

.component {
  .title {
    color: $primary-color;
    font-size: 2rem;

    &:hover {
      color: darken($primary-color, 10%);
    }
  }
}
</style>

React (CSS Modules)

// Button.module.scss
$primary: #007bff;
$hover: darken($primary, 10%);

.button {
  background: $primary;
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 0.25rem;
  cursor: pointer;

  &:hover {
    background: $hover;
  }

  &.large {
    padding: 0.75rem 1.5rem;
    font-size: 1.125rem;
  }
}

// Button.jsx
import styles from './Button.module.scss';

const Button = ({ children, large, ...props }) => {
  const className = `${styles.button} ${large ? styles.large : ''}`;

  return (
    <button className={className} {...props}>
      {children}
    </button>
  );
};

性能优化

编译性能优化

1. 使用 Dart Sass

# 安装 Dart Sass(推荐)
npm install sass

# 而不是 node-sass(已弃用)
# npm install node-sass

2. 启用缓存

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
            },
          },
          {
            loader: 'sass-loader',
            options: {
              sourceMap: true,
              sassOptions: {
                outputStyle: 'compressed',
              },
            },
          },
        ],
      },
    ],
  },
  cache: {
    type: 'filesystem',
  },
};

3. 代码分割

// 基础样式
// _base.scss
* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

// 组件样式
// _components.scss
@import 'components/button';
@import 'components/card';
@import 'components/modal';

// 页面样式
// _pages.scss
@import 'pages/home';
@import 'pages/about';
@import 'pages/contact';

// 主文件
// main.scss
@import 'variables';
@import 'mixins';
@import 'base';
@import 'components';
@import 'pages';

运行时性能优化

1. CSS 优化

// 避免深层嵌套
// ❌ 不好的做法
.header {
  .nav {
    .menu {
      .item {
        .link {
          color: blue;
        }
      }
    }
  }
}

// ✅ 更好的做法
.header-nav-link {
  color: blue;
}

// 或者使用 BEM 命名
.header {
  &__nav {
    // nav styles
  }

  &__nav-link {
    color: blue;
  }
}

2. 选择器优化

// ❌ 避免复杂选择器
.sidebar .widget .title h3 a {
  color: blue;
}

// ✅ 使用类选择器
.widget-title-link {
  color: blue;
}

// ✅ 或者适度嵌套
.widget {
  &__title-link {
    color: blue;
  }
}

选择建议

选择 SCSS 的情况

  1. 大型项目:需要强大的功能和模块系统
  2. 团队协作:成熟的生态系统和工具支持
  3. 长期维护:活跃的社区和持续更新
  4. 复杂逻辑:需要高级编程特性
// 适合复杂的主题系统
$themes: (
  light: (
    primary: #007bff,
    secondary: #6c757d,
    background: #ffffff,
    text: #212529,
  ),
  dark: (
    primary: #0d6efd,
    secondary: #6c757d,
    background: #212529,
    text: #ffffff,
  ),
);

@mixin theme($theme-name) {
  $theme: map-get($themes, $theme-name);

  @each $property, $value in $theme {
    --#{$property}: #{$value};
  }
}

.app {
  &[data-theme="light"] {
    @include theme(light);
  }

  &[data-theme="dark"] {
    @include theme(dark);
  }
}

选择 Less 的情况

  1. 快速原型:简单易学,快速上手
  2. 小型项目:功能需求不复杂
  3. 现有项目:已经使用 Less 的项目
  4. 性能要求:编译速度优先
// 适合简单的响应式设计
@mobile: ~"(max-width: 767px)";
@tablet: ~"(min-width: 768px) and (max-width: 1023px)";
@desktop: ~"(min-width: 1024px)";

.responsive-text {
  font-size: 16px;

  @media @mobile {
    font-size: 14px;
  }

  @media @tablet {
    font-size: 15px;
  }

  @media @desktop {
    font-size: 18px;
  }
}

选择 Sass(缩进语法)的情况

  1. 个人偏好:喜欢简洁的语法
  2. Python/Ruby 背景:习惯缩进语法
  3. 小团队:团队成员都熟悉缩进语法
// 简洁的语法风格
$colors: (
  primary: #007bff,
  secondary: #6c757d,
  success: #28a745
)

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

  .bg-#{$name}
    background-color: $color

    &:hover
      background-color: darken($color, 10%)

实际项目应用

项目结构示例

src/
├── styles/
│   ├── abstracts/
│   │   ├── _variables.scss
│   │   ├── _functions.scss
│   │   ├── _mixins.scss
│   │   └── _placeholders.scss
│   ├── base/
│   │   ├── _reset.scss
│   │   ├── _typography.scss
│   │   └── _utilities.scss
│   ├── components/
│   │   ├── _buttons.scss
│   │   ├── _cards.scss
│   │   ├── _forms.scss
│   │   └── _navigation.scss
│   ├── layout/
│   │   ├── _header.scss
│   │   ├── _footer.scss
│   │   ├── _sidebar.scss
│   │   └── _grid.scss
│   ├── pages/
│   │   ├── _home.scss
│   │   ├── _about.scss
│   │   └── _contact.scss
│   ├── themes/
│   │   ├── _light.scss
│   │   └── _dark.scss
│   └── main.scss

主文件配置

// main.scss
// 1. 抽象层
@import 'abstracts/variables';
@import 'abstracts/functions';
@import 'abstracts/mixins';
@import 'abstracts/placeholders';

// 2. 基础层
@import 'base/reset';
@import 'base/typography';
@import 'base/utilities';

// 3. 布局层
@import 'layout/grid';
@import 'layout/header';
@import 'layout/footer';
@import 'layout/sidebar';

// 4. 组件层
@import 'components/buttons';
@import 'components/cards';
@import 'components/forms';
@import 'components/navigation';

// 5. 页面层
@import 'pages/home';
@import 'pages/about';
@import 'pages/contact';

// 6. 主题层
@import 'themes/light';
@import 'themes/dark';

变量管理

// _variables.scss
// 颜色系统
$white: #ffffff;
$gray-100: #f8f9fa;
$gray-200: #e9ecef;
$gray-300: #dee2e6;
$gray-400: #ced4da;
$gray-500: #adb5bd;
$gray-600: #6c757d;
$gray-700: #495057;
$gray-800: #343a40;
$gray-900: #212529;
$black: #000000;

// 主题色
$primary: #007bff;
$secondary: $gray-600;
$success: #28a745;
$info: #17a2b8;
$warning: #ffc107;
$danger: #dc3545;
$light: $gray-100;
$dark: $gray-800;

// 字体系统
$font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;

$font-size-base: 1rem;
$font-size-lg: $font-size-base * 1.25;
$font-size-sm: $font-size-base * 0.875;

$font-weight-lighter: lighter;
$font-weight-light: 300;
$font-weight-normal: 400;
$font-weight-bold: 700;
$font-weight-bolder: bolder;

$line-height-base: 1.5;
$line-height-lg: 2;
$line-height-sm: 1.25;

// 间距系统
$spacer: 1rem;
$spacers: (
  0: 0,
  1: $spacer * 0.25,
  2: $spacer * 0.5,
  3: $spacer,
  4: $spacer * 1.5,
  5: $spacer * 3,
);

// 断点系统
$grid-breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px,
  xxl: 1400px
);

// 容器最大宽度
$container-max-widths: (
  sm: 540px,
  md: 720px,
  lg: 960px,
  xl: 1140px,
  xxl: 1320px
);

// 边框
$border-width: 1px;
$border-color: $gray-300;
$border-radius: 0.25rem;
$border-radius-lg: 0.3rem;
$border-radius-sm: 0.2rem;

// 阴影
$box-shadow-sm: 0 0.125rem 0.25rem rgba($black, 0.075);
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15);
$box-shadow-lg: 0 1rem 3rem rgba($black, 0.175);

// 过渡
$transition-base: all 0.2s ease-in-out;
$transition-fade: opacity 0.15s linear;
$transition-collapse: height 0.35s ease;

混合库

// _mixins.scss

// 响应式断点
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
  $min: breakpoint-min($name, $breakpoints);
  @if $min {
    @media (min-width: $min) {
      @content;
    }
  } @else {
    @content;
  }
}

@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {
  $max: breakpoint-max($name, $breakpoints);
  @if $max {
    @media (max-width: $max) {
      @content;
    }
  } @else {
    @content;
  }
}

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

@mixin text-truncate-multiline($lines: 2) {
  display: -webkit-box;
  -webkit-line-clamp: $lines;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

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

// 居中对齐
@mixin center-block {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

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

// 按钮样式
@mixin button-variant($background, $border, $color: color-contrast($background)) {
  color: $color;
  background-color: $background;
  border-color: $border;
  box-shadow: $btn-box-shadow;

  &:hover {
    color: $color;
    background-color: shade-color($background, $btn-hover-bg-shade-amount);
    border-color: shade-color($border, $btn-hover-border-shade-amount);
  }

  &:focus,
  &.focus {
    color: $color;
    background-color: shade-color($background, $btn-hover-bg-shade-amount);
    border-color: shade-color($border, $btn-hover-border-shade-amount);
    box-shadow: 0 0 0 $btn-focus-width rgba(mix($color, $border, 15%), 0.5);
  }

  &:active,
  &.active {
    color: $color;
    background-color: shade-color($background, $btn-active-bg-shade-amount);
    border-color: shade-color($border, $btn-active-border-shade-amount);

    &:focus {
      box-shadow: 0 0 0 $btn-focus-width rgba(mix($color, $border, 15%), 0.5);
    }
  }

  &:disabled,
  &.disabled {
    color: $color;
    background-color: $background;
    border-color: $border;
  }
}

// 动画
@mixin animation($animation) {
  -webkit-animation: $animation;
  -moz-animation: $animation;
  -o-animation: $animation;
  animation: $animation;
}

@mixin keyframes($name) {
  @-webkit-keyframes #{$name} {
    @content;
  }
  @-moz-keyframes #{$name} {
    @content;
  }
  @-o-keyframes #{$name} {
    @content;
  }
  @keyframes #{$name} {
    @content;
  }
}

// 渐变
@mixin gradient-bg($color: null) {
  background-color: $color;

  @if $enable-gradients {
    background-image: var(--#{$variable-prefix}gradient);
  }
}

@mixin gradient-x($start-color: $gray-700, $end-color: $gray-800, $start-percent: 0%, $end-percent: 100%) {
  background-image: linear-gradient(to right, $start-color $start-percent, $end-color $end-percent);
}

@mixin gradient-y($start-color: $gray-700, $end-color: $gray-800, $start-percent: 0%, $end-percent: 100%) {
  background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent);
}

总结

Sass、Less 和 SCSS 都是优秀的 CSS 预处理器,各有特色:

主要特点总结

  • Sass(缩进语法):简洁优雅,适合喜欢 Python/Ruby 风格的开发者
  • SCSS:功能最强大,生态最完善,适合大型项目和团队协作
  • Less:简单易学,编译快速,适合快速原型和小型项目

推荐选择

  1. 新项目推荐 SCSS:功能完整、社区活跃、工具支持好
  2. 现有 Less 项目:可以继续使用,迁移成本较高
  3. 个人项目:根据个人喜好选择,三者都能满足基本需求

学习建议

  1. 从基础开始:先掌握变量、嵌套、混合等基本概念
  2. 实践为主:在实际项目中应用和练习
  3. 关注最佳实践:学习代码组织、命名规范、性能优化
  4. 跟进发展:关注新特性和工具更新

无论选择哪种预处理器,关键是要理解其核心概念,掌握最佳实践,并在实际项目中灵活运用。随着 CSS 原生功能的不断增强(如 CSS 变量、嵌套等),预处理器的作用可能会发生变化,但它们在可预见的未来仍将是前端开发的重要工具。

四下皆无人