scss精华总结

一、 环境搭建

本篇演示使用vite 搭建一个简单的项目来看演示效果。搭建步骤如下:

1、 新建一个项目vite-scss

2、 初始化项目: pnpm init,这时候会生成packages.json

3、 安装vite: pnpm i vite -D

4、 在packages.json中添加打包命令

js 复制代码
"scripts": {
    "dev": "vite",
    "build": "vite build"
},

5、 安装sass: pnpm i sass -D

6、 根目录下新建index.html作为vite 的入口文件

7、 根目录下面创建src 目录

8、 src 下面创建css 目录和js目录

9、 css 目录下创建index.scss

10、 js 目录下创建index.js

11、 index.js中引入index.csss

12 index.html中引入index.js , 注意scrpit标签上必须添加type="module"

搭建完成之后目录结构如下:

13、 运行项目:pnpm run dev

14、 预览效果: 打开浏览器输入http://localhost:5173

二、scss 嵌套语法

在早期的原生csss是不支持嵌套的写法的,所以我们为了css 样式尽量的不出现覆盖,我们会一直在前面重复写父级的类名来规避。会非常麻烦,这个时候就scss就很好的解决了这个问题。scss提供了嵌套写法,使得我们不用重复写父级的类名,且结构更加清晰易读。现在我们用scss来写一个简单的导航:

html 结构如下

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>vite+scss</title>
  </head>
  <body>
    <nav>
      <a href="#">首页</a>
      <a href="#">列表</a>
      <a href="#">个人中心</a>
    </nav>
    <script src="./src/js/index.js" type="module"></script>
  </body>
</html>

index.scss

css 复制代码
nav {
  display: flex;
  justify-content: space-around;
  box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.3);
  a {
    color: #333;
    text-decoration: none;
    padding: 6px 16px;
  }
}

浏览器f12可以在浏览器调试工具中看到编译后css:

可以看到我们编写scss 被编译成了普通的css

三、scss 中变量的使用

在早期的css 中同样不支持变量的写法,这样使得我们在实现某些需求的时候就非常麻烦,比如说现在有一个需求,要开发一个产品,这个产品有不同的品牌,不同品牌之间除了颜色不同外其他基本相同,这个时候如果没有scss 我们可能就会想着写两套代码,来实现这个需求,这样就需要维护两套代码,造成了很大的维护成本,产品更新的时候需要两套代码同时更新。而有了scss 变量 就可以很好的解决这个问题。还是以之前的导航为例:

html 结构中增加选中导航的类名:

在src/css下面增加品牌配置变量的scss文件,brand.scss

scss 复制代码
// 品牌主风格颜色变量
$color: blue;
$active-bg: yellow;

根目录新增vite.config.js配置文件,内容如下:

js 复制代码
// vite.config.js
import { defineConfig } from "vite";
import path from "path";

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `
          @use "@/css/brand.scss" as *; 
        `, // 配置全局scss
      },
    },
  },
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"), // 配置别名
    },
  },
});

修改index.scss

scss 复制代码
nav {
  display: flex;
  justify-content: space-around;
  box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.3);
  a {
    color: $color; // 使用导航文字颜色变量
    text-decoration: none;
    padding: 6px 16px;

    &.active{ // 选中的类样式
      background: $active-bg; // 使用选中的颜色变量
      color: #fff;
    }
  }
}

主要修改以下内容:

这样要把不同品牌的代码发布到不同平台就非常简单了,只需要修改brand.scss中的变量,然后重新打包发布即可。甚至你可以将不同品牌的变量写成多个文件,通过命令的mode参数引用不同的文件。

上面的scss代码编译后同样会生成普通的css,将变量替换为我们定义时候的值:

四、混合指令

scss 的混合指令可以减少样式中相同部分样式的书写,来直接看例子

1. 不带参数的混合指令

html 结构:

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>vite+scss</title>
  </head>
  <body>
    <button class="primary">按钮</button>
    <button class="sucecss">按钮</button>
    <script src="./src/js/index.js" type="module"></script>
  </body>
</html>

index.scss

scss 复制代码
@mixin button-style{ // 定义按钮的混合指令
  padding: 8px 20px;
  font-size: 16px;
  border-radius: 5px;
  color: #fff;
  border: none;
  outline: none
}

.primary{
  @include button-style; // 引用按钮的混合指令
  background: #409EFF;
}

.sucecss {
  @include button-style; // 引用按钮的混合指令
  background: #67C23A;
}

运行效果:

编译成css 后的样子:

可以看到混合指令在编译后,会把混合指令中的样式复制到引用混合指令的地方。

2. 带参数的混合指令

混合指令可以像js中函数一样可以传递参数,通过传递参数可以增强代码的复用性和可维护性。将上述按钮的scss实现代码优化一下。

scss 复制代码
@mixin button-style($bg-color){ // 定义按钮的混合指令
  padding: 8px 20px;
  font-size: 16px;
  border-radius: 5px;
  color: #fff;
  border: none;
  outline: none;
  background: $bg-color;
}

.primary{
  @include button-style(#409EFF); // 引用按钮的混合指令
}

.sucecss {
  @include button-style(#67C23A); // 引用按钮的混合指令
}

主要修改部分:

查看编译结果:

可以看到编译结果和之前是一样的。

3. 带有默认参数值的混合指令

和es6中的函数一样,混合指令的参数也可以定义默认值。具体使用方式如下:

index.scss

scss 复制代码
@mixin button-style($bg-color: #409EFF){ // 定义按钮的混合指令
  padding: 8px 20px;
  font-size: 16px;
  border-radius: 5px;
  color: #fff;
  border: none;
  outline: none;
  background: $bg-color;
}

.primary{
  @include button-style; // 引用按钮的混合指令
}

.sucecss {
  @include button-style(#67C23A); // 引用按钮的混合指令
}

主要修改内容:

可以看到我们将.primary的背景颜色值定义为了默认颜色,调用时不用传参就能达到我们想要的效果。

五、扩展/继承指令

扩展/继承指令 和混合指令功能有点类似,但也有很大差别。

  • 相同点: 都是为了实现一些样式属性的复用
  • 不同点: 混合指令可以传参数,扩展/继承指令不能传参数,混合指令编译后是将定义混合指令里的内容复制到引用混合的地方,而扩展/继承指令则是将这些相同的部分抽离成分组选择器。

来看扩展/继承指令 的使用:

scss 复制代码
.btn { // 定义按钮的混合指令
  padding: 8px 20px;
  font-size: 16px;
  border-radius: 5px;
  color: #fff;
  border: none;
  outline: none;
}

.primary{
  @extend .btn; // 引用按钮的混合指令
  background: #409EFF;
}

.sucecss {
  @extend .btn; // 引用按钮的混合指令
  background: #67C23A;
}

可以看到扩展/继承指令使用@extend 来实现。编译结果如下:

可以看到,@extend 比混合指令的编译出来的代码更简洁。

六、站位符%

细心的你可能会发现上面我们实现的继承的代码中的.btn这个类名编译后我们并不需要它,但是编译后它仍然存在,这不是我们想要的。这个时候就可以使用站位符来解决这个问题。

修改index.scss

scss 复制代码
%btn { // 定义按钮的混合指令
  padding: 8px 20px;
  font-size: 16px;
  border-radius: 5px;
  color: #fff;
  border: none;
  outline: none;
}

.primary{
  @extend %btn; // 引用按钮的混合指令
  background: #409EFF;
}

.sucecss {
  @extend %btn; // 引用按钮的混合指令
  background: #67C23A;
}

可以看到占位符以%开头,后面跟选择器名称,注意不要点

看看编译结果:

可以看到btn 在编译后就不存在了。

总结一下混合指令,扩展/继承指令,占位符的优缺点:

  • 三者都可以在看开发阶段节省代码
  • 混合指令,可以传参数,可以根据参数来决定渲染,开发阶段看上去更简单灵活,但是编译后代码重复的相对较多。
  • 继承普通类如果直接继承一个类,而这个类在html结构中又没有使用到,编译后则会多出一些无用的类
  • 继承占位符,如果继承的类在html结构中没有用到,则使用占位符代替,使得代码编译后更简洁

综上所述:在需要传参时优先使用混合指令,如果一个被继承的类在html结构中有使用到,则直接使用继承普通类名称,如果被继承的类在html结构中没有被使用到则使用占位符

七、父选择器 &

其实在之前的导航案例中我们就用到了 &,接下来就来介绍下 & 的用法

scss 复制代码
nav {
  &.list{
    color: #333;
  }
}

nav {
  & .list {
    color: #333;
  }
}
nav {
  .list & {
    color: #333;
  }
}

编译结果:

可以看到 & 有三种用法,所以写的时候要知道自己需要的是哪种,它们编译后的结果是不一样的。第一种方式是最常用的。后面两种几乎不用。

七、总结

本篇介绍了scss 最常用的5个功能,运用好它们让我们在项目开发中写出的代码更简洁,更高效,在选择混合选择器,继承/扩展指令,占位符时要注意哪个场景适合它们。

今天的分享就到这里了,感谢收看

相关推荐
橙子家4 小时前
浏览器缓存之【结构化数据库与缓存】: IndexedDB、Cache storage 和 Storage buckets
前端
user20585561518134 小时前
X6 中边悬浮置顶,规避 `mouseleave` 事件丢失问题
前端
李明卫杭州4 小时前
CSS aspect-ratio 属性完全指南
前端
Pedantic6 小时前
SwiftUI 手势层级(Gesture Hierarchy)详解
前端
飘尘6 小时前
前端转型全栈(Java后端)的快速上手指引
前端·后端·全栈
一颗烂土豆7 小时前
Meshopt 压缩深度解析,为什么它比 Draco 更快
前端·javascript·webgl
浏览器工程师8 小时前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
雨季mo浅忆8 小时前
VSCode自动格式化三要素
前端
爱勇宝8 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员