Sass、Less 和 SCSS 的区别及用法详解
目录
概述
CSS 预处理器是一种用于扩展 CSS 功能的工具,它们允许开发者使用变量、嵌套、混合、函数等高级特性来编写更加灵活和可维护的样式代码。目前最流行的三种 CSS 预处理器是 Sass、Less 和 SCSS。
CSS 预处理器简介
什么是 CSS 预处理器?
CSS 预处理器是一种脚本语言,它扩展了 CSS 的功能,并将其编译成标准的 CSS 代码。它们提供了以下主要优势:
- 变量支持:定义可重用的值
- 嵌套规则:更直观的层级结构
- 混合(Mixins):可重用的代码块
- 函数和运算:动态计算样式值
- 模块化:更好的代码组织
- 继承:减少代码重复
为什么使用预处理器?
- 提高开发效率:减少重复代码编写
- 增强可维护性:更好的代码结构和组织
- 支持复杂逻辑:条件语句、循环等
- 团队协作:统一的代码风格和规范
Sass 详解
Sass 简介
Sass(Syntactically Awesome StyleSheets)是最早的 CSS 预处理器之一,由 Hampton Catlin 于 2006 年创建。Sass 有两种语法格式:
- 缩进语法(.sass):使用缩进和换行来定义代码块
- 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 的情况
- 大型项目:需要强大的功能和模块系统
- 团队协作:成熟的生态系统和工具支持
- 长期维护:活跃的社区和持续更新
- 复杂逻辑:需要高级编程特性
// 适合复杂的主题系统
$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 的情况
- 快速原型:简单易学,快速上手
- 小型项目:功能需求不复杂
- 现有项目:已经使用 Less 的项目
- 性能要求:编译速度优先
// 适合简单的响应式设计
@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(缩进语法)的情况
- 个人偏好:喜欢简洁的语法
- Python/Ruby 背景:习惯缩进语法
- 小团队:团队成员都熟悉缩进语法
// 简洁的语法风格
$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:简单易学,编译快速,适合快速原型和小型项目
推荐选择
- 新项目推荐 SCSS:功能完整、社区活跃、工具支持好
- 现有 Less 项目:可以继续使用,迁移成本较高
- 个人项目:根据个人喜好选择,三者都能满足基本需求
学习建议
- 从基础开始:先掌握变量、嵌套、混合等基本概念
- 实践为主:在实际项目中应用和练习
- 关注最佳实践:学习代码组织、命名规范、性能优化
- 跟进发展:关注新特性和工具更新
无论选择哪种预处理器,关键是要理解其核心概念,掌握最佳实践,并在实际项目中灵活运用。随着 CSS 原生功能的不断增强(如 CSS 变量、嵌套等),预处理器的作用可能会发生变化,但它们在可预见的未来仍将是前端开发的重要工具。