分类
标签
API设计 BEM Core Web Vitals CSRF CSS CSS-in-JS CSS变量 Flexbox Grid HTTP HTTP-2 HTTP-3 HTTPS JavaScript Less RESTful Sass SSL-TLS Stylus WebSocket Web安全 Web性能 XSS 主题切换 全双工通信 前端 前端优化 前端安全 前端工程化 前端开发 前端架构 动画 后端开发 响应式设计 团队协作 媒体查询 子网格 实时通信 容器查询 层叠层 布局 性能优化 接口规范 架构设计 模块化 渲染性能 现代CSS 用户体验 移动优先 组件库 缓存策略 网络 网络协议 网络安全 网络请求 自定义属性 认证授权 设计令牌 设计系统 过渡 预处理器 颜色函数
1781 字
9 分钟
CSS 预处理器完全指南
CSS 预处理器完全指南
概述
CSS 预处理器通过引入变量、嵌套、混合等编程特性,极大地提升了 CSS 的开发效率和可维护性。
Sass (SCSS 语法)
1. 基础特性
/* 变量定义 */
$primary-color: #007bff;
$secondary-color: #6c757d;
$font-size-base: 16px;
$spacing-unit: 8px;
/* 嵌套 */
.navbar {
background-color: $primary-color;
padding: $spacing-unit * 2;
.nav-item {
display: inline-block;
margin-right: $spacing-unit;
.nav-link {
color: white;
text-decoration: none;
&:hover {
text-decoration: underline;
}
&.active {
font-weight: bold;
}
}
}
}
/* 混合器 */
@mixin button-variant($bg-color, $text-color) {
background-color: $bg-color;
color: $text-color;
border: 1px solid darken($bg-color, 10%);
border-radius: 4px;
padding: 10px 20px;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
background-color: darken($bg-color, 10%);
border-color: darken($bg-color, 20%);
}
&:active {
transform: translateY(1px);
}
}
/* 使用混合器 */
.btn-primary {
@include button-variant($primary-color, white);
}
.btn-secondary {
@include button-variant($secondary-color, white);
}
2. 高级特性
/* 条件语句 */
@mixin responsive-padding($size) {
@if $size == small {
padding: 10px;
} @else if $size == medium {
padding: 20px;
} @else if $size == large {
padding: 30px;
} @else {
padding: $size;
}
}
.card {
@include responsive-padding(medium);
}
/* 循环 */
@for $i from 1 through 12 {
.col-#{$i} {
width: percentage($i / 12);
}
}
/* 列表和映射 */
$colors: (
primary: #007bff,
secondary: #6c757d,
success: #28a745,
danger: #dc3545
);
@each $name, $color in $colors {
.text-#{$name} {
color: $color;
}
.bg-#{$name} {
background-color: $color;
}
}
/* 函数 */
@function spacing($multiplier: 1) {
@return $spacing-unit * $multiplier;
}
.container {
padding: spacing(2); /* 16px */
margin: spacing(3); /* 24px */
}
/* 继承 */
%button-base {
display: inline-block;
padding: 10px 20px;
border-radius: 4px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
border: 1px solid transparent;
}
.btn {
@extend %button-base;
}
.btn-primary {
@extend %button-base;
background-color: $primary-color;
color: white;
&:hover {
background-color: darken($primary-color, 10%);
}
}
Less
1. 基础特性
/* 变量定义 */
@primary-color: #007bff;
@secondary-color: #6c757d;
@font-size-base: 16px;
@spacing-unit: 8px;
/* 嵌套 */
.navbar {
background-color: @primary-color;
padding: @spacing-unit * 2;
.nav-item {
display: inline-block;
margin-right: @spacing-unit;
.nav-link {
color: white;
text-decoration: none;
&:hover {
text-decoration: underline;
}
&.active {
font-weight: bold;
}
}
}
}
/* 混合器 */
.button-variant(@bg-color, @text-color) {
background-color: @bg-color;
color: @text-color;
border: 1px solid darken(@bg-color, 10%);
border-radius: 4px;
padding: 10px 20px;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
background-color: darken(@bg-color, 10%);
border-color: darken(@bg-color, 20%);
}
&:active {
transform: translateY(1px);
}
}
/* 使用混合器 */
.btn-primary {
.button-variant(@primary-color, white);
}
.btn-secondary {
.button-variant(@secondary-color, white);
}
2. 高级特性
/* 守卫(条件语句) */
.button-variant(@bg-color, @text-color) when (lightness(@bg-color) >= 50%) {
border-color: darken(@bg-color, 20%);
}
.button-variant(@bg-color, @text-color) when (lightness(@bg-color) < 50%) {
border-color: lighten(@bg-color, 20%);
}
/* 循环 */
.loop(@counter) when (@counter > 0) {
.col-@{counter} {
width: percentage(@counter / 12);
}
.loop(@counter - 1);
}
.loop(12);
/* 内置函数 */
.container {
padding: unit(@spacing-unit * 2, px);
margin: unit(@spacing-unit * 3, px);
color: lighten(@primary-color, 20%);
background-color: darken(@secondary-color, 10%);
}
/* 命名空间 */
#button-styles {
.variant(@bg-color, @text-color) {
background-color: @bg-color;
color: @text-color;
}
}
.btn {
#button-styles > .variant(@primary-color, white);
}
Stylus
1. 基础特性
/* 变量定义 */
primary-color = #007bff
secondary-color = #6c757d
font-size-base = 16px
spacing-unit = 8px
/* 嵌套 */
.navbar
background-color primary-color
padding spacing-unit * 2
.nav-item
display inline-block
margin-right spacing-unit
.nav-link
color white
text-decoration none
&:hover
text-decoration underline
&.active
font-weight bold
/* 混合器 */
button-variant(bg-color, text-color)
background-color bg-color
color text-color
border 1px solid darken(bg-color, 10%)
border-radius 4px
padding 10px 20px
cursor pointer
transition all 0.3s ease
&:hover
background-color darken(bg-color, 10%)
border-color darken(bg-color, 20%)
&:active
transform translateY(1px)
/* 使用混合器 */
.btn-primary
button-variant(primary-color, white)
.btn-secondary
button-variant(secondary-color, white)
2. 高级特性
/* 条件语句 */
responsive-padding(size)
if size == 'small'
padding 10px
else if size == 'medium'
padding 20px
else if size == 'large'
padding 30px
else
padding size
.card
responsive-padding('medium')
/* 循环 */
for i in 1..12
.col-{i}
width (i / 12) * 100%
/* 内置函数 */
.container
padding unit(spacing-unit * 2, 'px')
margin unit(spacing-unit * 3, 'px')
color lighten(primary-color, 20%)
background-color darken(secondary-color, 10%)
/* 插值 */
prefix = 'btn'
.{prefix}-primary
background-color primary-color
项目架构
1. 目录结构
src/styles/
├── base/
│ ├── _reset.scss
│ ├── _typography.scss
│ └── _variables.scss
├── components/
│ ├── _buttons.scss
│ ├── _cards.scss
│ └── _forms.scss
├── layouts/
│ ├── _header.scss
│ ├── _footer.scss
│ └── _grid.scss
├── utils/
│ ├── _mixins.scss
│ ├── _functions.scss
│ └── _helpers.scss
├── themes/
│ ├── _light.scss
│ └── _dark.scss
└── main.scss
2. 主文件组织
// main.scss
// 1. 基础样式
@import 'base/reset';
@import 'base/typography';
@import 'base/variables';
// 2. 工具类
@import 'utils/mixins';
@import 'utils/functions';
@import 'utils/helpers';
// 3. 布局
@import 'layouts/grid';
@import 'layouts/header';
@import 'layouts/footer';
// 4. 组件
@import 'components/buttons';
@import 'components/cards';
@import 'components/forms';
// 5. 主题
@import 'themes/light';
@import 'themes/dark';
// 6. 页面特定样式
@import 'pages/home';
@import 'pages/about';
@import 'pages/contact';
最佳实践
1. 变量管理
// _variables.scss
// 颜色系统
$colors: (
primary: #007bff,
secondary: #6c757d,
success: #28a745,
danger: #dc3545,
warning: #ffc107,
info: #17a2b8,
light: #f8f9fa,
dark: #343a40
);
// 字体系统
$font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
$font-size-base: 16px;
$font-weight-normal: 400;
$font-weight-bold: 700;
$line-height-base: 1.6;
// 间距系统
$spacing-unit: 8px;
$spacings: (
0: 0,
1: $spacing-unit,
2: $spacing-unit * 2,
3: $spacing-unit * 3,
4: $spacing-unit * 4,
5: $spacing-unit * 5
);
// 边框系统
$border-radius-base: 4px;
$border-width: 1px;
$border-color: #dee2e6;
// 阴影系统
$box-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.12);
$box-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
$box-shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
2. 混合器设计
// _mixins.scss
// 响应式断点
@mixin respond-to($breakpoint) {
@if map-has-key($breakpoints, $breakpoint) {
@media #{map-get($breakpoints, $breakpoint)} {
@content;
}
} @else {
@warn "Breakpoint `#{$breakpoint}` not found in `$breakpoints` map.";
}
}
// 清除浮动
@mixin clearfix {
&::after {
content: '';
display: table;
clear: both;
}
}
// 文本截断
@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 media($query) {
@media #{$query} {
@content;
}
}
3. 函数库
// _functions.scss
// 颜色函数
@function color($name, $variant: 'base') {
@if map-has-key($colors, $name) {
$color-map: map-get($colors, $name);
@if map-has-key($color-map, $variant) {
@return map-get($color-map, $variant);
} @else {
@warn "Variant `#{$variant}` not found for color `#{$name}`.";
@return map-get($color-map, 'base');
}
} @else {
@warn "Color `#{$name}` not found in `$colors` map.";
@return #000;
}
}
// 间距函数
@function spacing($multiplier: 1) {
@return $spacing-unit * $multiplier;
}
// 字体大小函数
@function font-size($size) {
@if map-has-key($font-sizes, $size) {
@return map-get($font-sizes, $size);
} @else {
@warn "Font size `#{$size}` not found.";
@return $font-size-base;
}
}
// 响应式函数
@function breakpoint($name) {
@if map-has-key($breakpoints, $name) {
@return map-get($breakpoints, $name);
} @else {
@warn "Breakpoint `#{$name}` not found.";
@return null;
}
}
构建工具集成
1. Webpack 配置
// webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'sass-loader',
options: {
sassOptions: {
includePaths: ['src/styles'],
outputStyle: 'compressed',
},
},
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
],
};
2. Gulp 配置
// gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const autoprefixer = require('gulp-autoprefixer');
const cleanCSS = require('gulp-clean-css');
gulp.task('styles', () => {
return gulp.src('src/styles/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer())
.pipe(cleanCSS())
.pipe(gulp.dest('dist/css'));
});
gulp.task('watch', () => {
gulp.watch('src/styles/**/*.scss', gulp.series('styles'));
});
3. Vite 配置
// vite.config.js
export default {
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "./src/styles/variables.scss";`,
},
},
},
};
性能优化
1. 代码分割
// 按需加载样式
// main.scss
@import 'components/buttons';
@import 'components/cards';
// admin.scss (管理员专用)
@import 'components/admin/forms';
@import 'components/admin/tables';
2. 缓存策略
// 使用版本控制
// 在构建时生成带哈希的文件名
// styles.abc123.css
3. 按需导入
// 使用 @use 替代 @import (Sass)
@use 'sass:color';
@use 'sass:map';
.button {
background-color: color.adjust(#007bff, $lightness: 10%);
}
迁移策略
1. 从纯CSS迁移
// 步骤1:重命名 .css 为 .scss
// 步骤2:逐步引入变量和混合器
// 步骤3:重构嵌套结构
// 步骤4:引入高级特性
2. 跨预处理器迁移
// Sass → Less
// 1. 变量语法:$var → @var
// 2. 混合器语法:@mixin → .mixin()
// 3. 函数差异:darken() → darken()
// Less → Stylus
// 1. 变量语法:@var → var
// 2. 括号可选:.mixin() → mixin
// 3. 分号可选
工具与资源
1. 开发工具
- Sass: dart-sass, node-sass
- Less: less.js, less-loader
- Stylus: stylus, stylus-loader
2. 编辑器插件
- VS Code: Sass, Less, Stylus 语法高亮
- WebStorm: 内置支持
- Sublime Text: 相关插件
3. 在线工具
- Sassmeister: 在线 Sass 编译器
- Less Playground: 在线 Less 编译器
- Stylus Try: 在线 Stylus 编译器
总结
CSS 预处理器是现代前端开发的重要工具,它们提供了:
- 更好的可维护性:变量、混合器、函数
- 更高的开发效率:嵌套、继承、循环
- 更强的表达能力:条件语句、计算
- 更好的团队协作:模块化、命名规范
选择合适的预处理器需要考虑:
- 团队熟悉度
- 项目需求
- 生态系统
- 构建工具集成
随着 CSS 原生特性的发展,预处理器的某些功能可能被替代,但它们仍然在大型项目中发挥着重要作用。
创建时间:2022-09-30 最后更新:2022-09-30 作者:前端开发团队 标签:CSS, Sass, Less, Stylus, 预处理器, 前端工程化
