Appearance
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层)
- 重用混合宏和函数
- 使用语义化的类名
- 定期清理未使用的代码
- 使用版本控制管理预处理器文件
- 文档化自定义混合宏和函数的用法