整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

SCSS揭秘:写出更智能简洁的样式代码

scss是sass的另一种语法,Sass是一种CSS预处理器,允许开发者编写更具结构性、可维护性和动态性的样式表

scss保持了css的语法结构,同时具备sass的强大功能,可以简单理解为一种增强版的css,除css含有功能外,还包含但不限于更优的变量、嵌套规则、混合、函数、动态运算等,文件后缀名为scss

安装与设置

在浏览器前端中,正常是不能直接使用scss的,其是一种CSS预处理器,即需要通过编译,生成对应的css文件,再进行使用

  • 首先需要安装Node.jsnpm
  • 接着用npm安装Sass,可以选择全局安装-g

  • 编译scss或sass为css

    • sass命令后接两个路径,第一个路径example.scss为待编译的scss文件所在路径,第二个example.css为生成的css保存路径,可以用相对路径也可以用绝对路径

基础语法

SCSS整体语法与CSS基本类似,其是CSS的一个超集,在SCSS内写CSS也是完全可以的

注释

SCSS的注释主要有两种形式,一种为//,另一种为/**/,与Js类似

变量

SCSS的变量用$来声明,使用时直接通过$ + 名称调用即可,变量数据可以是数字字符串颜色布尔值null,甚至还可以是ListMap

变量可以使用在几乎任何需要的地方,如属性值,属性名合成、复杂运算、函数调用等

CSS变量相比:

  • SCSS变量的作用域类似块作用域,在一个规则内定义的变量只能在该规则及其子规则内使用;CSS变量的作用域是基于DOM树结构,变量在一个元素作用域内定义,那么在该元素及其子元素的任何作用域(选择器)内均可使用
  • SCSS变量主要在编译阶段使用,其最终会将变量值整合到编译后的CSS中,相当于变量值的占位符,不会包含在编译后的CSS中;CSS变量主要在运行时使用,因此也可用JS动态更改

声明规则$name: value;

形式与样式属性类似,$后接名称即为变量名,冒号后面跟变量值

变量声明后,在其之后的位置依旧可以重新声明赋值

举个栗子

编译后的CSS如下:

  • 编译后的CSS是比较简洁的,SCSS的变量值在经过计算后被整合到CSS中了

了解一下即可,我们在定义值为字符串的变量时,有两种写法,带引号和不带引号,两者都能正常使用

带引号的可用于表达式计算

不带引号的一般不用于表达式计算(容易报错),而是直接使用

内置变量

除了自己定义的变量外,SCSS还包含一些内置变量,其分布在不同模块内,使用时需另行导入

示例如下

需注意的是,内置变量是不支持重新自定义赋值的

嵌套

在使用CSS写一些子元素样式时,很多时候都需要带上其父元素,以使选择器更精准或提高其优先级,但当大量书写类似属性时,每次都需要带上其父元素选择器,这其实的重复的工作

SCSS则可以规避这种情况,其支持嵌套使用

选择器嵌套

  • 子元素选择器直接嵌套在父元素选择器规则内即可
  • 在选择器规则内,可用&引用当前选择器,常用于配合伪类选择器使用,此时不会发生嵌套行为

编译后的CSS如下:

属性嵌套

嵌套除了用在选择器外,其还可以用在样式属性中,如下:

编译后如下:

算术运算

SCSS支持对变量或值进行运算,支持 +-*/%==!=>< 等运算符,对于不同单位之间的运算,运算结果取第一个值的单位,如果值之间只有一个有单位,则运算结果就取该单位

在介绍运算前,先介绍一个新的规则@debug,其用于帮助在开发过程中查看一些变量值或表达式值,SCSS运行后会将@debug后面的内容输出到控制台,类似Js的输出语句

比较运算

普通运算

需要注意的是,除法/比较特殊,其只在以下三种情况会进行除法运算:

  • 值,或值的一部分,是变量或者函数的返回值
  • 值被圆括号包裹
  • 值是算数表达式的一部分

但是,如果你的SCSS版本较高,可能会收到一个warning警告,官方团队不推荐直接使用/的形式进行除法运算,这是由于在CSS/也作为分隔符使用

官方更推荐使用sass:math模块的math.div函数或calc函数来执行除法运算,如下:

颜色运算

除了普通值运算外,SCSS还支持颜色值之间的运算

需注意的是,这在高版本的SCSS中已经弃用,高版本如需计算颜色,推荐使用sass:color模块内的颜色函数

插值

插值,即将SCSS表达式用#{}包围,作用是将SCSS表达式结果嵌入到CSS

插值几乎可以使用在SCSS样式表的所有位置,如:选择器名、属性名、属性值、变量值、动画名等

编译后的CSS为:

带引号字符串

在插值内使用带引号的字符串时,解析时会将引号去掉

编译后为:

使用时需思考是否要带引号,否则可能导致超乎预期的结果

导入

一个项目的样式往往是很多的,而我们一般不会将其完全放在一个文件内,一般会按某种规则区分,存放于多个文件内,不同文件需共享时就导入

SCSSCSS具有类似的导入语法@import,其允许多个导入用逗号分隔,导入文件后缀sass/scss可省略,如下:

但是,官方团队不鼓励继续使用该规则,其将在未来几年内逐步淘汰它,并最终从语言中删除

原因是:

  • @import使所有变量、混入和函数都可以全局访问,这使得人们很难分辨任何定义的位置
  • 由于一切都是全局的,因此库必须为其所有成员添加前缀,以避免命名冲突
  • @extend规则也是全局性的,这使得很难预测哪些样式规则将被扩展
  • 每个样式表的@import都会被执行,每次编辑时都会重新输出CSS,这会增加编译时间并产生臃肿的输出
  • 无法定义下游样式表无法访问的私有成员或占位符选择器

官方更推荐使用@use来导入模块,以这种方式加载的任何样式都将在编译的 CSS 输出中只包含一次,无论这些样式被加载了多少次

@use具有和@import同样的功能,并且它还具有命名空间,以避免命名冲突,默认其命名空间即为文件名,也可以用as设置

对于自己编写的文件,如果不在意命名冲突,也可完全导入,此时即可直接使用

高级功能

除了一些常见功能外,SCSS还具备一些高级功能,如:控制语句、函数等

条件和循环

条件语句主要使用@if@else@else if,效果于常见编程语言类似,如下:

以上SCSS会根据$pos变量值动态选择生成的justify-content

编译后CSS为:

循环语句主要有三个:@each@for@while

  • @each主要可用于变量ListMap

  • 编译后CSS

  • @for主要是从一个数字遍历到另一个数字,有两种形式:
    • @for <索引变量名> from <a> to <b>,这种不包含最后一个数字,范围为[a, b)
    • @for <索引变量名> from <a> through <b>,这种会包含最后一个数字,范围为[a, b]

  • 编译后的CSS如下:

  • @while是基于表达式结果的循环,当结果为false时退出循环

  • 编译后的CSS为:

函数

与Js类似,函数用于封装、定义一些复杂操作

  • 参数:函数的参数主要支持以下几类:
    • 普通参数:与变量名声明差不多,多个参数用,逗号分隔
    • 可选参数:到默认值的参数,默认值可以是任何表达式,甚至可以引用前面的参数
    • 任意参数:声明参数时,参数名最后以...结尾,表示接收余下所有参数
  • 返回:需返回值可采用@return返回
  • 调用:调用通过函数名调用,括号内传参数,除了按顺序传参数之外,还可通过关键字传参,即使用参数名后冒号跟值的方式

一些示例如下:

有趣的事实

与所有Scss标识符一样,函数名称将连字符和下划线视为相同,这意味着is-center和is_center两者都引用相同的函数,这是早期的历史遗留物,当时它只允许在标识符名称中使用下划线

混入

使用@mixin定义,使用@include引用,用于定义一些可以在整个样式表中重复使用的样式,其与函数类似,也可执行复杂操作、传入参数等,主要用于定义一些复杂的、规则的通用样式

语法如下:

  • @mixin <name> {语句}
  • @mixin <name> (参数列表) {语句}

引用如下:

  • @include <name>
  • @include <name>(参数值列表)

一些示例

@content用于表示自定义内容,使用时会将{}内的内容注入到@content所占位置

继承

继承是基于选择器的,其实现一个选择器可以继承另一个选择器的所有样式,包括组合样式(如伪类选择器样式)

默认浏览器样式不可继承,因为其不属于样式表样式

示例

编译后的CSS如下:

编译与调试

SCSS是一款CSS预处理器,其具备部分高级编程语言的特性,因此其需要经过编译使用,其也可以进行调试

编译

SCSS是需要经过编译,变成CSS才可以正常使用的,这在上面已经提到

编译单个文件比较简单,在命令行输入sass空格后接文件名即可,如需生成对应CSS文件,则在原有命令后再接空格加生成文件名即可

不想每次都运行命令重新编译,也可以通过添加命令参数--watch以监听编译,此时不必关闭控制台,系统会监听所编译SCSS文件的变化,但内容改变则重新编译,具体如下

如需停止监听,只需在控制台按Ctrl + C即可

调试

SCSS提供了几个命令用于开发调试

  • @debug用于输出调试内容
  • @warn用于输出警告内容,不会终止程序运行编译,但控制台会有警告信息
  • @error用于输出错误信息,会终止程序运行编译,同时在控制台输出错误信息

参考资料

SCSS模块文档:https://sass.bootcss.com/documentation/modules.html
SCSS官网:https://sass.bootcss.com

载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。

原文出处:https://wanago.io/2018/07/16/webpack-4-course-part-two-webpack-4-course-part-two-loaders/

今天继续我们的Webpack 4入门教程。在介绍了Webpack的基本概念之后,是时候更深入一点了。这次我们会涉及Webpack中非常强大的一个东西:loader。首先,我们会学习如何使用那些可用的loader。它将包括如何处理css、scss、图片以及对老版本的JavaScript语言的转换。让我们开始吧!

Webpack 4 入门教程继续 - 什么是loaders?

在之前的教程,我说Webpack是一个打包器。但这不是它仅有的目的。虽然Webpack天生只能理解JavaScript文件,但可以利用loader来改变这一点。除了能够处理多种类型的文件,Webpack还能修改它们。

添加loader

使用loader最好的方式是在webpack.config.js文件中指定它们。要这么做,你需要添加module.rules属性。

css-loader

css-loader能够翻译引入的css文件。

npm install css-loader

考虑如下的配置

// webpack.config.js
module.exports = {
 module: {
 rules: [
 {
 test: /\.css$/,
 use: 'css-loader'
 }
 ]
 }
};

rules

rules 这个属性是一个数组,指明你的各个loader。它会作用于匹配到 test 属性所指定规则的每一个文件。这个规则,实际上,是一个正则表达式。

use

属性 use 指明需要对匹配的文件应用那个loader。

串联多个loader

有了上面的代码,你就能够在你的JavaScript代码中导入css文件了。(例如,使用之前我们提到的ES6模块)

但这还不能让css真正生效。我们需要一种方法让浏览器能够使用这些css。这种情况下,style-loader就派上用场了。

npm install style-loader

但那就意味着要对css文件使用两个loader。你可以通过串联多个loader(chaining loaders)来使它们都生效。

// webpack.config.js
module.exports = {
 module: {
 rules: [
 {
 test: /\.css$/,
 use: ['style-loader', 'css-loader']
 }
 ]
 },
}

你可以看到,我们给了 use 属性一个数组。一个非常重要的注意点是,串联执行的顺序是反向的(译者注:也就是从右往左)。

/* style.css */
body {
 background-color:black;
}
// index.js
import './style.css'

使用上面的配置,打包的工作方式大概是:

  1. Webpack尝试解析 style.css 文件
  2. 文件名与正则表达式/\.css$/匹配
  3. 文件被 css-loader 编译
  4. css-loader 处理后的结果会被传到 style-loader
  5. 最后,style-loader 返回一串JavaScript代码

默认情况下,打包后的输出是./dist/bundle.js。现在,这个文件包含的代码会把所有的样式插入到<style>标签里面。如果你在HTML中引入了bundle.js的连接,在执行完脚本后,HTML会看起来像这样:

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
 <title>Webpack App</title>
 <style type="text/css">body {
 background-color:black;
 }</style></head>
 <body>
 <script type="text/javascript" src="bundle.js"></script>
 </body>
</html>

sass-loader

有了这些知识,你可以轻松地给你的工程添加sass/scss支持了。你可以在这里使用 sass-loader

npm install sass-loader

只需要在你的loader链里插入它:

// webpack.config.js
module.exports = {
 module: {
 rules: [
 {
 test: /\.scss$/,
 use: ['style-loader', 'css-loader', 'sass-loader']
 }
 ]
 },
}

就是这样,现在你可以引入scss文件了!文件在被 css-loader 解析之前,会从scss转译成纯css。

(译者注: 如果安装完sass-loader后,本地运行Webpack出现了和node-sass相关的错误,可尝试再安装一个node-sass的包解决这个问题,即npm install node-sass)

给loader传入选择项

实际上,loader可以接受一些选择项。让我们用 url-loader 为例来说明。

npm install url-loader file-loader
// webpack.config.js
module.exports = {
 module: {
 rules: [
 {
 test: /\.scss$/,
 use: ['style-loader', 'css-loader','sass-loader']
 },
 {
 test: /\.(png|jpg|gif)$/,
 use: [
 {
 loader: 'url-loader',
 options: {
 limit: 5000
 }
 }
 ]
 }
 ]
 }
};

注意,如果你想要给loader传入配置项,你不再是把loader以字符串形式给 use 属性。现在它是一个对象,包含两个属性: loader(即loader的名字),和 options

url-loader会把你的图片转换为base64格式的URI。如果你的图片文件很小,那么把它们直接引入到代码中会有更好的性能。这可以减少浏览器所发的请求数。但是,如果你的图片文件很大,那么把它们作为单独的文件引入可能会更好,因为浏览器可以并行加载它们。

这就是为什么 url-loader 有一个 limit 属性。它指明了一个文件大小(以byte为单位),当超过这个大小时,文件将不会被转为base64的URI。相比较而言,file-loader 仅仅是被用来拷贝你的文件。

body {
 background-image: url('./big-background.png');
}
.icon {
 background-image: url('./icon.png');
}

上面的配置会得到下面的结果:

<style type="text/css">body {
 background-image: url(ca3ebe0891c7823ff1e137d8eb5b4609.png); }
.icon {
 background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAALElEQVR4AWMYIWAU1FPLoP9AXEFI0QEi8H+YYdQyqIEaXuumRhh1DZdUMwoATlYWfwh9eYkAAAAASUVORK5CYII=); }
</style>

因为big-background.png比限制的大小更大,它被拷贝至dist文件夹,并被起了一个随机的名字。而相反,icon.png文件被转换为了base64 URI。

使用babel转译JavaScript

另一个流行的loader是 babel-loader。它允许你使用Babel转译JavaScript文件。它解决了如何使用最新版本的JavaScript来编写代码的问题。如果你想支持老版本的浏览器,或者想使用现代浏览器还没有实现的功能,Babel都能够帮到你。

npm install babel-loader @babel/core @babel/preset-env

(译者注:原文的babel-core和babel-preset-env依赖被替换为@babel/core和@babel/preset-enve,因为新版本的Babel7中对官方提供的依赖使用了命名空间@babel)

module.exports = {
 module: {
 rules: [
 {
 test: /\.js$/,
 exclude: /(node_modules)/,
 use: {
 loader: 'babel-loader',
 options: {
 presets: ['@babel/preset-env']
 }
 }
 }
 ]
 }
};

注意到,我们这里使用了 exclude 属性,它也是一个正则表达式。如果任何文件与这个表达式相匹配,它将不会被转译。

这里有很多预置项可以满足你的需求。查阅Babel的官方文档,你可以在那里找到它们的列表。

总结

这一次我们学习了Webpack很有用的一个功能:loader。我们介绍了一些可用的loader。利用它们,我们在项目中添加上了对scss的支持。此外,我们还学习如何使用 url-loader 处理图片。另外一个loader的常用之处是我们讨论的利用Babel转译JavaScript。在教程未来的部分,我们会深入到loader中,包括写一个我们自己的loader。

关于葡萄城:

赋能开发者!葡萄城公司成立于 1980 年,是全球领先的集开发工具、商业智能解决方案、管理系统设计工具于一身的软件和服务提供商。西安葡萄城是其在中国的分支机构,面向全球市场提供软件研发服务,并为中国企业的信息化提供国际先进的开发工具、软件和研发咨询服务。葡萄城的控件和软件产品在国内外屡获殊荣,在全球被数十万家企业、学校和政府机构广泛应用。​

import

Sass 拓展了 @import 的功能,允许其导入 SCSS 或 Sass 文件。被导入的文件将合并编译到同一个 CSS 文件中,另外,被导入的文件中所包含的变量或者混合指令 (mixin) 都可以在导入的文件中使用。

例如:

public.scss

$font-base-color:#333;

index.scss

@import "public";
$color:#666;
.container{
    border-color: $color;
    color: $font-base-color; 
}

编译后:

.container { border-color: #666; color: #333; }

注意:跟我们普通css里面@import的区别


但是如下的几种方式,都将作为普通的 CSS 语句,不会导入任何 Sass 文件

  • 文件拓展名是 .css;
  • 文件名以 http:// 开头;
  • 文件名是 url();
  • @import 包含 media queries。
@import "public.css";
@import url(public);
@import "http://xxx.com/xxx";

局部文件(Partials)

Sass源文件中可以通过@import指令导入其他Sass源文件,被导入的文件就是*局部文件*,局部文件让Sass模块化编写更加容易。


如果一个目录正在被Sass程序监测,目录下的所有scss/sass源文件都会被编译,但通常不希望局部文件被编译,因为局部文件是用来被导入到其他文件的。如果不想局部文件被编译,文件名可以以下划线 (_)开头

_theme.scss

$border-color:#999;
$background-color:#f2f2f2;

index.scss

@import "public";
@import "theme";
$color:#666;
.container{
    border-color: $border-color;
    color: $font-base-color; 
    background-color: $background-color;
}

编译后:

.container { border-color: #999; color: #333; background-color: #f2f2f2; }

可以看到,@import 引入的theme.scss,可以没有下划线(__),这是允许的,这也就意味着,同一个目录下不能同时出现两个相关名的sass文件(一个不带,一个带_),添加下划线的文件将会被忽略。

嵌套 @import


大多数情况下,一般在文件的最外层(不在嵌套规则内)使用 @import,其实,也可以将 @import 嵌套进 CSS 样式或者 @media 中,与平时的用法效果相同,只是这样导入的样式只能出现在嵌套的层中。

base.scss

.main-color{
    color: #F00;
}

index.scss

.container{
    @import "base";
}

最后生成

.container .main-color { color: #F00; }

注意:被导入的文件不能是局部文件方式(在前面不能加_)