在当今的前端开发领域,样式表语言的进步已经显著提升了代码组织性和可维护性。Sass(Syntactically Awesome Style Sheets)
作为CSS预处理器的翘楚,以其强大的变量、嵌套规则、混合宏(mixin)、循环和函数等高级特性,正在引领一种革命性的编写CSS的新方式。通过掌握Sass的这些高级用法,开发者能够有效地减少样式冗余,提升工作效率,并构建出更易于理解和扩展的样式结构。
引述一个具体的实践场景,想象一个大型项目中存在大量的重复颜色、尺寸或动画定义,使用Sass变量,可以将这些共享值统一管理,一处变更即全局生效。此外,借助@each
循环语句,我们可以轻松地为一组类名生成具有不同颜色主题的一系列样式,避免了手动编写多条相似规则所带来的繁琐与潜在错误。
而诸如嵌套规则这样的功能,则允许我们以更加直观的方式模拟DOM结构,使得CSS选择器之间的层级关系更为清晰可见。同时,通过自定义混合宏,复杂的样式块得以模块化封装和复用,从而极大地降低了代码重复度,提高整体代码质量。
因此,深入学习并运用Sass的高级用法不仅简化了样式编写过程,也有助于构建出适应性强、扩展性好且易于维护的CSS代码库,是现代Web开发实践中不可或缺的一部分。
例举几个常见的用法:
一、控制指令
Sass提供了控制指令,允许你在样式表中使用条件语句和循环,从而更加灵活地控制样式的生成。
1. @if和@else if/else
Sass中的@if
、@else if
和@else
指令允许你根据条件判断来输出不同的样式。
css
$is-dark: true;
body {
@if $is-dark {
background-color: black;
color: white;
} @else {
background-color: white;
color: black;
}
}
2.@for
Sass的@for
指令可以用于循环输出样式,支持两种循环方式:from <start> through <end>
和from <start> to <end>
。
css
@for $i from 1 through 3 {
.item-#{$i} { width: 10px * $i; }
}
二、函数
Sass内置了一系列函数,可以用于处理颜色、数值和字符串等,同时你也可以定义自己的函数。
1.内置函数
Sass内置函数如darken()
、lighten()
、opacity()
等,用于操作颜色值。
css
$base-color: #333;
.dark-text {
color: darken($base-color, 10%);
}
.light-text {
color: lighten($base-color, 20%);
}
2.自定义函数
你可以使用@function
指令定义自己的Sass函数。
css
@function em($px) {
@return $px / 16 * 1em;
}
h1 {
font-size: em(32); // 等同于 font-size: 2em;
}
三、扩展/占位符
Sass的扩展(Extend)和占位符(Placeholder)功能,可以帮助你避免重复编写相同的样式代码。
1.扩展(@extend)
@extend
允许你共享一组CSS属性的选择器。
css
.message {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
.success {
@extend .message;
border-color: green;
}
.error {
@extend .message;
border-color: red;
}
2.占位符(%)
占位符类似于类选择器,但它不会直接输出到CSS中,只有当它被@extend
时才会被渲染。
css
%ir {
display: inline-block;
background-color: transparent;
border: none;
padding: 0;
/* ... */
}
button {
@extend %ir;
font-size: 1rem;
/* ... */
}
四、Map数据结构
Sass支持Map数据结构,它允许你存储键值对,并通过键来访问对应的值。
1、map-get
css
$font-sizes: (
xsmall: 12px,
small: 14px,
medium: 16px,
large: 18px,
xlarge: 20px
);
h1 {
font-size: map-get($font-sizes, large);
}
2、map-merge
map-merge
是Sass中的一个函数,用于将两个map(映射)合并成一个新的map。Sass中的映射表示一个或多个键值对,并且是不可改变的。因此,map-merge
函数会返回一个新的map,而不会更改原始的map。
具体来说,如果你有两个map,你可以使用map-merge
函数将它们合并为一个map。在合并过程中,如果两个map中存在相同的键,那么新map中的值将是第二个map中对应键的值,因为它会覆盖第一个map中的值。
css
$map1: (
key1: value1,
key2: value2
);
$map2: (
key2: value3,
key3: value4
);
$mergedMap: map-merge($map1, $map2);
// 输出:$mergedMap 为 (key1: value1, key2: value3, key3: value4)
五、使用@import合并文件
Sass允许你使用@import
指令来导入其他Sass文件,这样可以更好地组织你的样式代码。
css
// styles.scss
@import 'partials/variables';
@import 'partials/mixins';
@import 'partials/reset';
@import 'partials/layout';
@import 'partials/modules';
以上只是Sass高级用法的一部分,Sass还提供了更多强大的功能,如颜色运算、选择器嵌套等。掌握这些高级用法将使你在编写样式时更加得心应手,提高代码的可读性和可维护性。通过不断地实践和学习,你可以发掘Sass的更多潜力,并将其应用于实际项目中,创造出更加美观和高效的界面。
下面我们来列举几个实战例子,实战才是快速学习的捷径。
例子
需求1:我们需要在每个标题前添加不同颜色的小方块作为无序列表的原点。如图所示
常规做法:
css
.icon {
&::before {
content: '';
width: 8px;
height: 8px;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
}
}
.color-icon-1 {
background: #0096ff;
}
.color-icon-2 {
background: #ffcc00;
}
.color-icon-3 {
background: #00ffff;
}
.color-icon-4 {
background: #ff6363;
}
.color-icon-5 {
background: #00ccff;
}
.color-icon-6 {
background: #483B3B;
}
使用时就是 <p class="color-icon-1 icon" />
,这种写法极其不优雅,并且定义的样式也冗余。
下面使用Sass > (@each, @mixin)
进行二次封装
@each:
类似用JS中的for循环@mixin:
利用mixin创建的函数需使用@include注入
css
@mixin screenBefore(
$color,
$width: 0.13rem,
$height: 0.13rem
) {
&::before {
content: '';
width: $width;
height: $height;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
background: $color;
}
}
$colors: (
1:#0096ff,
2:#ffcc00,
3:#00ffff,
4:#ff6363,
5:#00ccff,
6:#483B3B
);
@each $colorIndex, $colorValue in $colors {
.color-icon-#{$colorIndex} {
@include screenBefore($colorValue )
}
}
是不是有写JS的既视感?
多参则利用列表去作为参数
css
$alarm-colors: (
1:(#d9001b, 0.17rem, 0.17rem),
2:(#8a00e1, 0.17rem, 0.17rem),
3:(#34d160, 0.17rem, 0.17rem),
4:(#00c6ff, 0.17rem, 0.17rem),
5:(#d9001b, 0.15rem, 0.15rem),
6:(#8a00e1, 0.15rem, 0.15rem),
7:(#34d160, 0.15rem, 0.15rem),
8:(#00c6ff, 0.15rem, 0.15rem)
);
@each $colorIndex, $colorValue in $alarm-colors {
$color: nth($colorValue, 1);
$width: nth($colorValue, 2);
$height: nth($colorValue, 3);
.screen-alarm-list-#{$colorIndex} {
@include screenBefore(
$color,
$width,
$height
)
}
}
}
需求二、利用map_merge实现主题的切换
现有两个颜色map的键值对文件
css
// theme-default
$theme-default {
colorPrimary: #FFF
}
// theme-blue
$theme-blue {
colorPrimary: blue
}
// 主要color-map
$themes: map_merge($theme-default, $theme-blue);
下面使用高级用法,列举一个全局注入主题样式的详细过程
1、首先定义一个高阶Sass插槽处理函数。
css
@mixin generateThemeContent($name, $theme) {
$globalTheme: $theme !global;
$globalThemeName: $name !global;
@if (str_length($name)>0) {
.theme-#{$name} {
@content;
}
} @else {
html {
@if ($generate_default) {
@content;
}
}
}
}
2、其次在Sass主入口文件中定义全局Mixin
css
@import './blue.scss'; // $theme-blue
@import './default.scss'; // $theme-default
$themes: map_merge($theme-default, $theme-blue);
$generate_default: true; // 触发插槽判断
@mixin theme {
@each $curThemeName, $curTheme in $themes {
@include generateThemeContent($curThemeName, $curTheme) {
@content;
}
}
}
拿Vue为例子,在其vue.config.js
配置中找到css
配置如下:
css
css: {
sourceMap: false,
loaderOptions: {
sass: {
prependData: `@import "src/styles/theme/global-import.scss";` // 在 sass-loader v8 中,这个选项名是 "prependData"
}
}
},
项目用法:
html
<style lang="scss" scoped>
@include theme {
// 这里可以尽情用主题中定义的变量
}
</style>
用好Sass/Less等这类的处理器,确实能大大减少我们的重复编写样式的工作用,并且增加可读性,更贴切逻辑性编写。