Appearance
Sass 工具与资源
Sass生态系统提供了丰富的工具和资源,帮助开发者提高工作效率、优化代码质量和简化开发流程。本章将详细介绍Sass开发中常用的工具和资源。
开发工具
编辑器和IDE插件
Visual Studio Code插件
json
// 推荐的VS Code扩展
{
"recommendations": [
"bradlc.vscode-tailwindcss", // Tailwind CSS智能提示
"csstools.postcss", // PostCSS支持
"ms-vscode.vscode-scss", // SCSS语言支持
"stylelint.vscode-stylelint", // Stylelint集成
"formulahendry.auto-rename-tag", // 自动重命名标签
"esbenp.prettier-vscode", // 代码格式化
"gruntfuggly.todo-tree", // TODO标记树
"aaron-bond.better-comments" // 改进注释高亮
]
}
WebStorm/IntelliJ IDEA配置
xml
<!-- WebStorm Sass配置 -->
<!-- Settings > Languages & Frameworks > Stylesheets > Sass/SCSS -->
<config>
<!-- Sass可执行文件路径 -->
<sass-compiler>
<executable-path>/path/to/sass</executable-path>
<watchers>
<watch-scss>true</watch-scss>
<watch-sass>true</watch-sass>
</watchers>
</sass-compiler>
<!-- 自动导入 -->
<auto-imports>
<import-abstracts>true</import-abstracts>
<resolve-partials>true</resolve-partials>
</auto-imports>
</config>
命令行工具
Sass命令行工具
bash
# 基本编译命令
sass input.scss output.css
# 监听文件变化
sass --watch input.scss output.css
# 监听整个目录
sass --watch scss:css
# 压缩输出
sass --style compressed input.scss output.css
# 生成源映射
sass --sourcemap input.scss output.css
# 使用自定义配置文件
sass --load-path=node_modules input.scss output.css
# 更多选项
sass --help
高级命令行用法
bash
# 条件编译
sass --style=compressed --no-source-map --quiet scss/main.scss css/main.min.css
# 多文件编译
sass scss/:css/ --style=expanded
# 带错误处理的编译
sass scss/main.scss css/main.css 2>&1 | tee sass-build.log
# 持续集成中的用法
sass --no-source-map --style=compressed --quiet-deps scss/main.scss dist/main.css
构建工具集成
Webpack配置
javascript
// webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
entry: './src/js/main.js', // 如果有JS入口
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[contenthash].js'
},
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
// 开发环境使用style-loader,生产环境使用MiniCssExtractPlugin
process.env.NODE_ENV !== 'production'
? 'style-loader'
: MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 2, // 在css-loader前执行的loader数量
sourceMap: true
}
},
{
loader: 'postcss-loader', // 可选,用于自动添加浏览器前缀
options: {
sourceMap: true,
postcssOptions: {
plugins: [
['autoprefixer', {}]
]
}
}
},
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
sourceMap: true,
sassOptions: {
includePaths: [
path.resolve(__dirname, 'node_modules'),
path.resolve(__dirname, 'src/scss')
],
outputStyle: process.env.NODE_ENV === 'production' ? 'compressed' : 'expanded'
}
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash].css',
chunkFilename: 'css/[id].[contenthash].css'
})
],
optimization: {
minimizer: [
new CssMinimizerPlugin({
test: /\.css$/g,
parallel: true, // 使用多进程并行运行来提高构建速度
})
],
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
type: 'css/mini-extract',
chunks: 'all',
enforce: true,
}
}
}
}
};
Vite配置
javascript
// vite.config.js
import { defineConfig } from 'vite';
import { resolve } from 'path';
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `
@use "@/styles/abstracts/variables" as *;
@use "@/styles/abstracts/mixins" as *;
`,
includePaths: [
resolve(__dirname, 'src/styles'),
resolve(__dirname, 'node_modules')
]
}
},
modules: {
localsConvention: 'camelCase' // CSS Modules配置
}
},
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
'@styles': resolve(__dirname, 'src/styles')
}
}
});
Gulp构建
javascript
// gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const sourcemaps = require('gulp-sourcemaps');
const autoprefixer = require('gulp-autoprefixer');
const cleanCSS = require('gulp-clean-css');
const rename = require('gulp-rename');
const gulpif = require('gulp-if');
const browserSync = require('browser-sync').create();
// 环境变量
const isProduction = process.env.NODE_ENV === 'production';
// Sass编译任务
gulp.task('sass', function() {
return gulp.src('src/scss/**/*.scss')
.pipe(gulpif(!isProduction, sourcemaps.init()))
.pipe(sass({
outputStyle: isProduction ? 'compressed' : 'expanded',
includePaths: ['node_modules', 'src/scss'],
sourceComments: !isProduction,
errLogToConsole: true
}).on('error', sass.logError))
.pipe(autoprefixer({
cascade: false,
grid: 'autoplace'
}))
.pipe(gulpif(isProduction, cleanCSS()))
.pipe(gulpif(!isProduction, sourcemaps.write('.')))
.pipe(gulp.dest('dist/css'))
.pipe(browserSync.stream());
});
// 监听任务
gulp.task('watch', function() {
browserSync.init({
server: {
baseDir: './'
}
});
gulp.watch('src/scss/**/*.scss', gulp.series('sass'));
gulp.watch('*.html').on('change', browserSync.reload);
});
// 默认任务
gulp.task('default', gulp.series('sass', 'watch'));
代码质量工具
Stylelint配置
json
// .stylelintrc.json
{
"extends": [
"stylelint-config-standard-scss",
"stylelint-config-recess-order"
],
"plugins": [
"stylelint-scss",
"stylelint-order",
"stylelint-prettier"
],
"rules": {
"at-rule-no-unknown": null,
"scss/at-rule-no-unknown": true,
"scss/dollar-variable-pattern": "^[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
"scss/percent-placeholder-pattern": "^[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
"scss/selector-nest-combinators": "always",
"scss/selector-no-redundant-nesting-selector": true,
"scss/at-extend-no-missing-placeholder": true,
"scss/double-slash-comment-whitespace-inside": "always",
"order/properties-order": [
[
"position",
"top",
"right",
"bottom",
"left",
"z-index",
"display",
"vertical-align",
"flex",
"flex-grow",
"flex-shrink",
"flex-basis",
"flex-direction",
"flex-wrap",
"flex-flow",
"justify-content",
"align-items",
"align-content",
"align-self",
"order",
"grid",
"grid-area",
"grid-template",
"grid-template-areas",
"grid-template-rows",
"grid-template-columns",
"grid-row",
"grid-row-start",
"grid-row-end",
"grid-column",
"grid-column-start",
"grid-column-end",
"grid-auto-rows",
"grid-auto-columns",
"grid-auto-flow",
"grid-gap",
"grid-row-gap",
"grid-column-gap",
"gap",
"row-gap",
"column-gap",
"margin",
"margin-top",
"margin-right",
"margin-bottom",
"margin-left",
"margin-block",
"margin-block-start",
"margin-block-end",
"margin-inline",
"margin-inline-start",
"margin-inline-end",
"padding",
"padding-top",
"padding-right",
"padding-bottom",
"padding-left",
"padding-block",
"padding-block-start",
"padding-block-end",
"padding-inline",
"padding-inline-start",
"padding-inline-end",
"float",
"clear",
"object-fit",
"overflow",
"overflow-x",
"overflow-y",
"overflow-scrolling",
"clip",
"clip-path",
"width",
"min-width",
"max-width",
"height",
"min-height",
"max-height",
"inline-size",
"min-inline-size",
"max-inline-size",
"block-size",
"min-block-size",
"max-block-size",
"box-sizing",
"writing-mode",
"resize",
"zoom",
"outline",
"outline-width",
"outline-style",
"outline-color",
"outline-offset",
"border",
"border-color",
"border-style",
"border-width",
"border-top",
"border-top-color",
"border-top-style",
"border-top-width",
"border-right",
"border-right-color",
"border-right-style",
"border-right-width",
"border-bottom",
"border-bottom-color",
"border-bottom-style",
"border-bottom-width",
"border-left",
"border-left-color",
"border-left-style",
"border-left-width",
"border-radius",
"border-top-left-radius",
"border-top-right-radius",
"border-bottom-right-radius",
"border-bottom-left-radius",
"border-start-start-radius",
"border-start-end-radius",
"border-end-start-radius",
"border-end-end-radius",
"border-image",
"border-image-source",
"border-image-slice",
"border-image-width",
"border-image-outset",
"border-image-repeat",
"border-collapse",
"border-spacing",
"background",
"background-color",
"background-image",
"background-attachment",
"background-repeat",
"background-position",
"background-position-x",
"background-position-y",
"background-clip",
"background-origin",
"background-size",
"background-blend-mode",
"color",
"font",
"font-family",
"font-size",
"font-style",
"font-weight",
"font-variant",
"font-size-adjust",
"font-stretch",
"font-effect",
"font-emphasize",
"font-emphasize-position",
"font-emphasize-style",
"font-smooth",
"line-height",
"text-align",
"text-align-last",
"vertical-align",
"text-overflow",
"text-transform",
"text-decoration",
"text-decoration-color",
"text-decoration-line",
"text-decoration-style",
"text-shadow",
"text-fill-color",
"text-stroke",
"text-stroke-width",
"text-stroke-color",
"letter-spacing",
"word-spacing",
"white-space",
"caption-side",
"tab-size",
"hyphens",
"overflow-wrap",
"word-wrap",
"word-break",
"quotes",
"counter-reset",
"counter-increment",
"list-style",
"list-style-position",
"list-style-type",
"list-style-image",
"table-layout",
"empty-cells",
"caption-side",
"display",
"visibility",
"unicode-bidi",
"direction",
"columns",
"column-span",
"column-width",
"column-count",
"column-fill",
"column-gap",
"column-rule",
"column-rule-width",
"column-rule-style",
"column-rule-color",
"break-before",
"break-inside",
"break-after",
"page-break-before",
"page-break-inside",
"page-break-after",
"orphans",
"widows",
"zoom",
"fill",
"fill-rule",
"clip-rule",
"stroke"
],
{
"unspecified": "bottom",
"empty-lines-between-override-groups": 1
}
]
}
}
Prettier配置
json
// .prettierrc
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": true,
"arrowParens": "avoid",
"endOfLine": "lf",
"overrides": [
{
"files": "*.scss",
"options": {
"parser": "scss"
}
},
{
"files": "*.sass",
"options": {
"parser": "sass"
}
}
]
}
在线工具和资源
在线Sass编辑器
html
<!-- 推荐的在线Sass工具 -->
<ul>
<li><a href="https://sass.js.org/">Sass.js</a> - 在线Sass编译器</li>
<li><a href="https://www.sassmeister.com/">SassMeister</a> - Sass在线编辑器</li>
<li><a href="https://codepen.io/">CodePen</a> - 支持Sass的在线代码编辑器</li>
<li><a href="https://jsfiddle.net/">JSFiddle</a> - 在线测试工具,支持Sass</li>
</ul>
颜色工具
scss
// 颜色管理工具和资源
/*
1. Coolors (https://coolors.co/)
- 快速生成配色方案
2. Adobe Color (https://color.adobe.com/)
- 专业的配色工具
3. Material Palette (https://www.materialpalette.com/)
- Material Design配色
4. Color Hunt (https://colorhunt.co/)
- 流行的配色方案
5. CSS Gradient (https://cssgradient.io/)
- 渐变生成器
*/
Sass框架和库
Bootstrap Sass
scss
// Bootstrap with Sass
// package.json
{
"dependencies": {
"bootstrap": "^5.3.0"
}
}
// main.scss
// 导入Bootstrap的Sass文件
@import "~bootstrap/scss/bootstrap";
// 或者按需导入
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins";
// 自定义变量
$primary: #007bff;
$secondary: #6c757d;
// 导入组件
@import "~bootstrap/scss/buttons";
@import "~bootstrap/scss/forms";
Foundation for Sites
scss
// Foundation框架
// package.json
{
"dependencies": {
"foundation-sites": "^6.7.0"
}
}
// main.scss
@import 'foundation';
// 启用特定组件
@include foundation-global-styles;
@include foundation-grid;
@include foundation-typography;
@include foundation-button;
@include foundation-forms;
Bulma
scss
// Bulma框架
// package.json
{
"dependencies": {
"bulma": "^0.9.4"
}
}
// main.scss
// 自定义变量
$primary: #007bff;
$info: #17a2b8;
$success: #28a745;
// 导入Bulma
@import "~bulma/bulma.sass";
实用Sass库
Sass MQ (媒体查询库)
scss
// _mq.scss - 媒体查询工具库
$mq-breakpoints: (
mobile: 320px,
tablet: 768px,
desktop: 1024px,
wide: 1200px
);
@mixin mq($from: null, $until: null, $and: null) {
$media-query: '';
@if $from {
$media-query: '#{$media-query} and (min-width: #{map-get($mq-breakpoints, $from)})';
}
@if $until {
$media-query: '#{$media-query} and (max-width: #{map-get($mq-breakpoints, $until) - 1px})';
}
@if $and {
$media-query: '#{$media-query} and #{$and}';
}
// Remove unnecessary ' and ' at the beginning
@if str-slice($media-query, 1, 5) == ' and ' {
$media-query: str-slice($media-query, 6);
}
@media #{$media-query} {
@content;
}
}
// 使用示例
.element {
font-size: 1rem;
@include mq($from: tablet) {
font-size: 1.2rem;
}
@include mq($from: desktop) {
font-size: 1.5rem;
}
}
Sass Flexbox Grid
scss
// _flexbox-grid.scss - Flexbox网格系统
$grid-columns: 12;
$grid-gutter: 30px;
%grid-container {
width: 100%;
padding-right: $grid-gutter / 2;
padding-left: $grid-gutter / 2;
margin-right: auto;
margin-left: auto;
}
%grid-row {
display: flex;
flex-wrap: wrap;
margin-right: -($grid-gutter / 2);
margin-left: -($grid-gutter / 2);
}
%grid-col {
position: relative;
width: 100%;
padding-right: $grid-gutter / 2;
padding-left: $grid-gutter / 2;
}
@for $i from 1 through $grid-columns {
%col-#{$i} {
flex: 0 0 percentage($i / $grid-columns);
max-width: percentage($i / $grid-columns);
}
}
性能优化工具
PurgeCSS (CSS清理工具)
javascript
// purgecss.config.js
module.exports = {
content: [
'./src/**/*.html',
'./src/**/*.js',
'./src/**/*.jsx',
'./src/**/*.ts',
'./src/**/*.tsx',
'./src/**/*.vue',
'./src/**/*.svelte'
],
css: [
'./dist/css/main.css'
],
extractors: [
{
extractor: content => {
// 自定义提取器
return content.match(/[\w-/:]+(?<!:)/g) || [];
},
extensions: ['html', 'js', 'jsx', 'ts', 'tsx', 'vue', 'svelte']
}
],
variables: true,
safelist: [
// 保持某些类不被删除
'active',
'show',
'hide',
/^alert-/,
/^btn-/,
/^col-/
]
};
代码分析工具
json
// .stylelintignore
# 忽略特定文件
dist/
node_modules/
vendor/
*.min.css
javascript
// 分析CSS复杂度的工具配置
// package.json
{
"scripts": {
"analyze:css": "css-analyzer dist/css/main.css",
"bundle-size": "webpack-bundle-analyzer --mode static dist/stats.json",
"lint:css": "stylelint 'src/**/*.scss'",
"format:css": "prettier --write 'src/**/*.scss'"
}
}
学习资源
官方文档和教程
markdown
## 官方资源
- [Sass官网](https://sass-lang.com/)
- [Sass指南](https://sass-lang.com/guide)
- [Sass文档](https://sass-lang.com/documentation)
## 学习平台
- [Sass Bites](https://sassbites.com/) - Sass教程
- [CSS-Tricks Sass指南](https://css-tricks.com/snippets/sass/)
- [Scotch.io Sass教程](https://scotch.io/tutorials/getting-started-with-sass)
## 社区资源
- [Sass Guidelines](https://sass-guidelin.es/) - Sass最佳实践
- [Hugo Giraudel的Sass资源](https://hugogiraudel.com/)
- [Sass Summit](https://sasssummit.com/) - Sass会议资源
代码规范和样式指南
scss
// .scss-lint.yml 或 .stylelintignore
# 推荐的Sass代码规范
# 基于Sass Guidelines (https://sass-guidelin.es/)
# 变量命名规范
# 使用连字符分隔,语义化命名
$primary-color: #007bff;
$border-radius-sm: 2px;
# 混合宏命名规范
# 动词开头,描述性命名
@mixin center-element { }
@mixin responsive-grid { }
# 选择器命名规范
# BEM方法论或类似规范
.component { }
.component__element { }
.component--modifier { }
这些工具和资源将帮助您更高效地使用Sass,提高代码质量和开发效率。