CSS 预处理器 - Sass
章节介绍
Sass(Syntactically Awesome Style Sheets)是目前最流行的 CSS 预处理器之一,它扩展了 CSS 的功能,提供了许多高级特性,如变量、混合、嵌套、继承等。这些特性可以大大提高 CSS 代码的可维护性、可重用性和开发效率。本章节将详细介绍 Sass 的核心特性和使用方法,帮助你掌握这个强大的 CSS 开发工具。
核心知识点讲解
1. Sass 的安装和使用
安装 Sass
Sass 可以通过多种方式安装,最常用的是通过 npm 安装:
# 全局安装
npm install -g sass
# 项目本地安装
npm install --save-dev sass基本使用
Sass 文件有两种扩展名:.scss 和 .sass。.scss 是 Sass 的新语法,兼容 CSS 语法;.sass 是旧语法,使用缩进代替大括号和分号。
# 编译单个文件
sass input.scss output.css
# 监视文件变化并自动编译
sass --watch input.scss:output.css
# 监视整个目录
sass --watch src/scss:dist/css2. 变量
变量是 Sass 最基本的特性之一,它允许你存储和重用值。
变量定义和使用
// 定义变量
$primary-color: #3498db;
$font-size: 16px;
$spacing: 10px;
// 使用变量
body {
font-size: $font-size;
color: $primary-color;
}
.container {
margin: $spacing;
padding: $spacing;
}变量作用域
Sass 变量有全局作用域和局部作用域:
// 全局变量
$color: red;
.container {
// 局部变量,只在 .container 内部有效
$color: blue;
color: $color; // 输出 blue
}
.text {
color: $color; // 输出 red
}变量插值
变量插值允许你在选择器、属性名和字符串中使用变量:
$prefix: btn;
.#{$prefix} {
display: inline-block;
padding: 10px 20px;
}
.#{$prefix}-primary {
background-color: #3498db;
color: white;
}3. 嵌套
嵌套是 Sass 的另一个核心特性,它允许你在选择器内部嵌套其他选择器,反映 HTML 的层次结构。
基本嵌套
nav {
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
display: inline-block;
margin-right: 10px;
}
a {
text-decoration: none;
color: #333;
&:hover {
color: #3498db;
}
}
}父选择器引用
使用 & 可以引用父选择器:
.btn {
display: inline-block;
padding: 10px 20px;
border: none;
border-radius: 4px;
&:hover {
opacity: 0.8;
}
&:active {
transform: translateY(1px);
}
&-primary {
background-color: #3498db;
color: white;
}
&-secondary {
background-color: #2ecc71;
color: white;
}
}4. 混合(Mixins)
混合是 Sass 中最强大的特性之一,它允许你创建可重用的样式块。
基本混合
// 定义混合
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
// 使用混合
.container {
@include flex-center;
height: 400px;
}
.card {
@include flex-center;
flex-direction: column;
}带参数的混合
// 定义带参数的混合
@mixin button($bg-color, $text-color: white, $padding: 10px 20px) {
display: inline-block;
padding: $padding;
background-color: $bg-color;
color: $text-color;
border: none;
border-radius: 4px;
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
// 使用带参数的混合
.btn-primary {
@include button(#3498db);
}
.btn-secondary {
@include button(#2ecc71, white, 8px 16px);
}带默认值的混合
// 定义带默认值的混合
@mixin box-shadow($shadow: 0 2px 4px rgba(0, 0, 0, 0.1)) {
-webkit-box-shadow: $shadow;
-moz-box-shadow: $shadow;
box-shadow: $shadow;
}
// 使用带默认值的混合
.card {
@include box-shadow;
}
.card-hover {
@include box-shadow(0 4px 8px rgba(0, 0, 0, 0.2));
}5. 继承
继承允许你从一个选择器继承样式到另一个选择器,减少代码冗余。
基本继承
// 基础样式
.btn {
display: inline-block;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
// 继承基础样式
.btn-primary {
@extend .btn;
background-color: #3498db;
color: white;
}
.btn-secondary {
@extend .btn;
background-color: #2ecc71;
color: white;
}占位符选择器
占位符选择器(以 % 开头)是一种特殊的选择器,它本身不会被编译到 CSS 中,只有被继承时才会生效:
// 占位符选择器
%btn {
display: inline-block;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
// 继承占位符选择器
.btn-primary {
@extend %btn;
background-color: #3498db;
color: white;
}
.btn-secondary {
@extend %btn;
background-color: #2ecc71;
color: white;
}6. 操作符
Sass 提供了各种操作符,如算术操作符、比较操作符、逻辑操作符等,可以在样式中进行计算。
算术操作符
$base-font-size: 16px;
$container-width: 960px;
$column-count: 3;
body {
font-size: $base-font-size;
}
.container {
width: $container-width;
margin: 0 auto;
}
.column {
width: $container-width / $column-count;
float: left;
margin-right: 20px;
&:last-child {
margin-right: 0;
}
}
.text-lg {
font-size: $base-font-size * 1.5;
}
.text-sm {
font-size: $base-font-size * 0.8;
}颜色操作
$primary-color: #3498db;
.btn {
background-color: $primary-color;
&:hover {
// 使颜色变暗 10%
background-color: darken($primary-color, 10%);
}
&:active {
// 使颜色变亮 5%
background-color: lighten($primary-color, 5%);
}
}
// 其他颜色函数
$color: #3498db;
// 调整饱和度
saturate($color, 10%);
// 降低饱和度
desaturate($color, 10%);
// 调整透明度
transparentize($color, 0.5);
// 混合颜色
mix($color, #fff, 50%);7. 函数
Sass 提供了许多内置函数,同时也允许你定义自己的函数。
内置函数
// 字符串函数
$string: "Hello, Sass!";
// 转换为大写
uppercase($string);
// 转换为小写
lowercase($string);
// 首字母大写
capitalize($string);
// 数字函数
$number: 10.5;
// 取整
round($number);
// 向上取整
ceil($number);
// 向下取整
floor($number);
// 列表函数
$list: 1, 2, 3, 4, 5;
// 获取列表长度
length($list);
// 获取列表中的元素
nth($list, 2);
// 映射函数
$map: (
primary: #3498db,
secondary: #2ecc71,
danger: #e74c3c
);
// 获取映射中的值
map-get($map, primary);
// 检查映射中是否存在键
map-has-key($map, primary);自定义函数
// 定义自定义函数
@function calculate-width($container-width, $column-count, $gutter) {
@return ($container-width - ($gutter * ($column-count - 1))) / $column-count;
}
// 使用自定义函数
.container {
width: 960px;
margin: 0 auto;
}
.column {
width: calculate-width(960px, 3, 20px);
float: left;
margin-right: 20px;
&:last-child {
margin-right: 0;
}
}8. 导入
Sass 的导入功能允许你将样式拆分成多个文件,提高代码的可维护性。
导入文件
// 导入变量
@import 'variables';
// 导入混合
@import 'mixins';
// 导入基础样式
@import 'base';
// 导入组件样式
@import 'components/buttons';
@import 'components/cards';
@import 'components/forms';
// 导入布局样式
@import 'layouts/header';
@import 'layouts/footer';
@import 'layouts/grid';部分文件
Sass 部分文件以 _ 开头,它们不会被单独编译成 CSS 文件,只能被其他文件导入:
scss/
├── _variables.scss
├── _mixins.scss
├── _base.scss
├── components/
│ ├── _buttons.scss
│ ├── _cards.scss
│ └── _forms.scss
├── layouts/
│ ├── _header.scss
│ ├── _footer.scss
│ └── _grid.scss
└── style.scss // 主文件,导入所有部分文件9. 控制指令
Sass 提供了控制指令,如 @if、@for、@each 和 @while,允许你在样式中使用逻辑控制。
@if 指令
$theme: dark;
body {
@if $theme == dark {
background-color: #333;
color: white;
} @else if $theme == light {
background-color: #fff;
color: #333;
} @else {
background-color: #f5f5f5;
color: #333;
}
}@for 指令
// 从 1 到 4 循环
@for $i from 1 through 4 {
.col-#{$i} {
width: 100% / 4 * $i;
}
}
// 从 1 到 3 循环
@for $i from 1 to 4 {
.mt-#{$i} {
margin-top: $i * 10px;
}
}@each 指令
// 遍历列表
$colors: primary #3498db, secondary #2ecc71, danger #e74c3c;
@each $name, $color in $colors {
.btn-#{$name} {
background-color: $color;
color: white;
}
}
// 遍历映射
$spacing: (
xs: 5px,
sm: 10px,
md: 15px,
lg: 20px,
xl: 30px
);
@each $name, $value in $spacing {
.m-#{$name} {
margin: $value;
}
.p-#{$name} {
padding: $value;
}
}@while 指令
$i: 1;
@while $i <= 5 {
.text-#{$i} {
font-size: 12px + $i * 2;
}
$i: $i + 1;
}实用案例分析
案例一:使用 Sass 变量管理颜色方案
场景描述
需要管理一个网站的颜色方案,确保颜色的一致性和可维护性。
实现代码
// _variables.scss
// 颜色变量
$colors: (
primary: #3498db,
secondary: #2ecc71,
danger: #e74c3c,
warning: #f39c12,
success: #27ae60,
dark: #333,
light: #f5f5f5,
gray: #999,
white: #fff
);
// 从映射中获取颜色值
@function color($key) {
@return map-get($colors, $key);
}
// _mixins.scss
// 按钮混合
@mixin button($color-key, $padding: 10px 20px) {
display: inline-block;
padding: $padding;
background-color: color($color-key);
color: color(white);
border: none;
border-radius: 4px;
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
// _buttons.scss
// 导入变量和混合
@import 'variables';
@import 'mixins';
// 按钮样式
.btn {
display: inline-block;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
.btn-primary {
@include button(primary);
}
.btn-secondary {
@include button(secondary);
}
.btn-danger {
@include button(danger);
}代码解析
- 颜色变量管理:使用映射存储所有颜色值,便于统一管理
- 颜色函数:创建
color()函数,方便从映射中获取颜色值 - 按钮混合:创建带参数的混合,根据颜色键生成不同样式的按钮
- 按钮样式:使用混合生成不同类型的按钮样式
案例二:使用 Sass 创建响应式网格系统
场景描述
需要创建一个响应式网格系统,支持不同屏幕尺寸下的布局调整。
实现代码
// _variables.scss
// 网格变量
$grid-columns: 12;
$grid-gutter: 20px;
// 断点变量
$breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
);
// 从映射中获取断点值
@function breakpoint($key) {
@return map-get($breakpoints, $key);
}
// _mixins.scss
// 响应式混合
@mixin responsive($breakpoint) {
@media (min-width: breakpoint($breakpoint)) {
@content;
}
}
// 网格列混合
@mixin col($columns, $total-columns: $grid-columns) {
width: ($columns / $total-columns) * 100%;
}
// _grid.scss
// 导入变量和混合
@import 'variables';
@import 'mixins';
// 容器样式
.container {
width: 100%;
padding-left: $grid-gutter / 2;
padding-right: $grid-gutter / 2;
margin-left: auto;
margin-right: auto;
@include responsive(sm) {
max-width: 540px;
}
@include responsive(md) {
max-width: 720px;
}
@include responsive(lg) {
max-width: 960px;
}
@include responsive(xl) {
max-width: 1140px;
}
}
// 行样式
.row {
display: flex;
flex-wrap: wrap;
margin-left: -$grid-gutter / 2;
margin-right: -$grid-gutter / 2;
}
// 列样式
.col {
position: relative;
width: 100%;
padding-left: $grid-gutter / 2;
padding-right: $grid-gutter / 2;
}
// 生成列类
@for $i from 1 through $grid-columns {
.col-#{$i} {
@include col($i);
}
@include responsive(sm) {
.col-sm-#{$i} {
@include col($i);
}
}
@include responsive(md) {
.col-md-#{$i} {
@include col($i);
}
}
@include responsive(lg) {
.col-lg-#{$i} {
@include col($i);
}
}
@include responsive(xl) {
.col-xl-#{$i} {
@include col($i);
}
}
}代码解析
- 网格变量:定义网格列数、间距和断点
- 响应式混合:创建
responsive()混合,生成媒体查询 - 网格列混合:创建
col()混合,计算列宽 - 容器样式:定义不同断点下的容器最大宽度
- 行和列样式:定义行和列的基本样式
- 生成列类:使用
@for指令生成不同断点下的列类
案例三:使用 Sass 管理字体和排版
场景描述
需要管理网站的字体和排版系统,确保字体大小、行高、字重等的一致性。
实现代码
// _variables.scss
// 字体变量
$fonts: (
primary: 'Arial', sans-serif,
secondary: 'Georgia', serif,
monospace: 'Courier New', monospace
);
// 字体大小变量
$font-sizes: (
xs: 12px,
sm: 14px,
base: 16px,
md: 18px,
lg: 20px,
xl: 24px,
xxl: 30px,
xxxl: 36px
);
// 行高变量
$line-heights: (
tight: 1.2,
normal: 1.5,
loose: 1.8
);
// 字重变量
$font-weights: (
light: 300,
normal: 400,
medium: 500,
semibold: 600,
bold: 700
);
// 从映射中获取值
@function font($key) {
@return map-get($fonts, $key);
}
@function font-size($key) {
@return map-get($font-sizes, $key);
}
@function line-height($key) {
@return map-get($line-heights, $key);
}
@function font-weight($key) {
@return map-get($font-weights, $key);
}
// _mixins.scss
// 排版混合
@mixin typography($size, $weight: normal, $line-height: normal) {
font-size: font-size($size);
font-weight: font-weight($weight);
line-height: line-height($line-height);
}
// _typography.scss
// 导入变量和混合
@import 'variables';
@import 'mixins';
// 基础排版
body {
font-family: font(primary);
@include typography(base);
color: #333;
}
// 标题样式
h1 {
@include typography(xxxl, bold, tight);
margin-bottom: font-size(md);
}
h2 {
@include typography(xxl, semibold, tight);
margin-bottom: font-size(sm);
}
h3 {
@include typography(xl, semibold, tight);
margin-bottom: font-size(sm);
}
h4 {
@include typography(lg, medium, normal);
margin-bottom: font-size(xs);
}
h5 {
@include typography(md, medium, normal);
margin-bottom: font-size(xs);
}
h6 {
@include typography(base, medium, normal);
margin-bottom: font-size(xs);
}
// 文本样式
.text-xs {
@include typography(xs);
}
.text-sm {
@include typography(sm);
}
.text-base {
@include typography(base);
}
.text-lg {
@include typography(lg);
}
.text-xl {
@include typography(xl);
}
// 字重样式
.font-light {
font-weight: font-weight(light);
}
.font-normal {
font-weight: font-weight(normal);
}
.font-medium {
font-weight: font-weight(medium);
}
.font-semibold {
font-weight: font-weight(semibold);
}
.font-bold {
font-weight: font-weight(bold);
}代码解析
- 字体变量:使用映射存储字体、字体大小、行高和字重
- 字体函数:创建函数从映射中获取字体相关值
- 排版混合:创建混合,根据参数设置字体样式
- 基础排版:设置 body 的基础字体样式
- 标题样式:使用混合设置不同级别标题的样式
- 文本样式:创建不同字体大小的文本类
- 字重样式:创建不同字重的文本类
Sass 项目结构最佳实践
推荐的项目结构
scss/
├── _variables.scss // 变量定义
├── _mixins.scss // 混合定义
├── _functions.scss // 函数定义
├── _reset.scss // 重置样式
├── _base.scss // 基础样式
├── components/ // 组件样式
│ ├── _buttons.scss // 按钮组件
│ ├── _cards.scss // 卡片组件
│ ├── _forms.scss // 表单组件
│ ├── _navigation.scss // 导航组件
│ └── _modals.scss // 模态框组件
├── layouts/ // 布局样式
│ ├── _header.scss // 头部布局
│ ├── _footer.scss // 页脚布局
│ ├── _grid.scss // 网格布局
│ └── _sidebar.scss // 侧边栏布局
├── pages/ // 页面特定样式
│ ├── _home.scss // 首页样式
│ ├── _about.scss // 关于页样式
│ └── _contact.scss // 联系页样式
├── utils/ // 工具类
│ ├── _typography.scss // 排版工具类
│ ├── _spacing.scss // 间距工具类
│ ├── _colors.scss // 颜色工具类
│ └── _flex.scss // Flexbox 工具类
└── style.scss // 主文件,导入所有部分文件导入顺序
- 变量、混合和函数:这些是基础,其他样式会依赖它们
- 重置和基础样式:重置浏览器默认样式,设置全局基础样式
- 组件样式:可重用组件的样式
- 布局样式:页面布局相关的样式
- 页面特定样式:特定页面的样式
- 工具类:通用的工具类
代码示例:完整的 Sass 项目示例
// style.scss
// 导入变量、混合和函数
@import 'variables';
@import 'mixins';
@import 'functions';
// 导入重置和基础样式
@import 'reset';
@import 'base';
// 导入组件样式
@import 'components/buttons';
@import 'components/cards';
@import 'components/forms';
@import 'components/navigation';
// 导入布局样式
@import 'layouts/header';
@import 'layouts/footer';
@import 'layouts/grid';
// 导入页面特定样式
@import 'pages/home';
@import 'pages/about';
@import 'pages/contact';
// 导入工具类
@import 'utils/typography';
@import 'utils/spacing';
@import 'utils/colors';
@import 'utils/flex';
// _variables.scss
// 颜色变量
$colors: (
primary: #3498db,
secondary: #2ecc71,
danger: #e74c3c,
warning: #f39c12,
success: #27ae60,
dark: #333,
light: #f5f5f5,
gray: #999,
white: #fff
);
// 字体变量
$fonts: (
primary: 'Arial', sans-serif,
secondary: 'Georgia', serif
);
// 字体大小变量
$font-sizes: (
xs: 12px,
sm: 14px,
base: 16px,
md: 18px,
lg: 20px,
xl: 24px
);
// 间距变量
$spacing: (
xs: 5px,
sm: 10px,
md: 15px,
lg: 20px,
xl: 30px,
xxl: 40px
);
// _mixins.scss
// 按钮混合
@mixin button($bg-color, $text-color: white, $padding: 10px 20px) {
display: inline-block;
padding: $padding;
background-color: $bg-color;
color: $text-color;
border: none;
border-radius: 4px;
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
// 响应式混合
@mixin responsive($breakpoint) {
@media (min-width: $breakpoint) {
@content;
}
}
// _base.scss
// 基础样式
body {
font-family: map-get($fonts, primary);
font-size: map-get($font-sizes, base);
line-height: 1.5;
color: map-get($colors, dark);
background-color: map-get($colors, light);
}
// 链接样式
a {
color: map-get($colors, primary);
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
// 标题样式
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: map-get($spacing, md);
font-weight: bold;
}
h1 {
font-size: map-get($font-sizes, xl);
}
h2 {
font-size: map-get($font-sizes, lg);
}
h3 {
font-size: map-get($font-sizes, md);
}
// _components/buttons.scss
// 按钮样式
.btn {
display: inline-block;
padding: map-get($spacing, sm) map-get($spacing, lg);
border: none;
border-radius: 4px;
cursor: pointer;
font-size: map-get($font-sizes, base);
font-weight: bold;
text-align: center;
text-decoration: none;
&:hover {
opacity: 0.8;
}
&:active {
transform: translateY(1px);
}
}
.btn-primary {
@include button(map-get($colors, primary));
}
.btn-secondary {
@include button(map-get($colors, secondary));
}
.btn-danger {
@include button(map-get($colors, danger));
}
// _utils/spacing.scss
// 间距工具类
@each $name, $value in $spacing {
.m-#{$name} {
margin: $value;
}
.mt-#{$name} {
margin-top: $value;
}
.mb-#{$name} {
margin-bottom: $value;
}
.ml-#{$name} {
margin-left: $value;
}
.mr-#{$name} {
margin-right: $value;
}
.p-#{$name} {
padding: $value;
}
.pt-#{$name} {
padding-top: $value;
}
.pb-#{$name} {
padding-bottom: $value;
}
.pl-#{$name} {
padding-left: $value;
}
.pr-#{$name} {
padding-right: $value;
}
}章节总结
本章节详细介绍了 Sass 预处理器的核心特性和使用方法,包括:
- 变量:存储和重用值,提高代码的可维护性
- 嵌套:反映 HTML 的层次结构,减少代码冗余
- 混合:创建可重用的样式块,支持参数和默认值
- 继承:从一个选择器继承样式到另一个选择器
- 操作符:在样式中进行计算,支持算术和颜色操作
- 函数:使用内置函数和自定义函数处理值
- 导入:将样式拆分成多个文件,提高代码的组织性
- 控制指令:使用逻辑控制指令生成样式
- 项目结构:推荐的 Sass 项目结构和导入顺序
通过本章节的学习,你应该能够:
- 安装和使用 Sass 预处理器
- 掌握 Sass 的核心特性,如变量、嵌套、混合、继承等
- 使用 Sass 创建可维护、可重用的样式代码
- 设计合理的 Sass 项目结构
- 应用 Sass 最佳实践,提高 CSS 开发效率
Sass 是一个强大的 CSS 开发工具,它可以大大提高你的开发效率和代码质量。通过合理使用 Sass 的特性,你可以编写更加简洁、可维护、可扩展的 CSS 代码,为项目的成功做出贡献。