前言
Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,这些拓展令 CSS 更加强大与优雅。使用 Sass 以及 Sass 的样式库(如 Compass)有助于更好地组织管理样式文件,以及更高效地开发项目。
官网地址:Sass教程 Sass中文文档 | Sass中文网
特色功能:
- 完全兼容 CSS3
- 在 CSS 基础上增加变量、嵌套 (nesting)、混合 (mixins) 等功能
- 通过函数进行颜色值与属性值的运算
- 提供控制指令 (control directives)等高级功能
- 自定义输出格式
导入依赖
我这里使用的是
vue2
项目,所以会使用npm/yarn/pnpm
安装依赖安装好依赖后,可以使用
npx sass ./src/....xxx.scss
命令,来单独编译scss,并在命令提示符中输出
npm install sass sass-loader -D # npm
pnpm add sass sass-loader -D # pnpm
语法格式
Sass有两种语法格式(sass、scss)
一种是scss:这种格式仅在 CSS3 语法的基础上进行拓展,所有 CSS3 语法在 SCSS 中都是通用的,同时加入 Sass 的特色功能
另一种是sass:被称为缩进格式 (Indented Sass) 通常简称 “Sass”,是一种简化格式。它使用 “缩进” 代替 “花括号” 表示属性属于某个选择器,用 “换行” 代替 “分号” 分隔属性,很多人认为这样做比 SCSS 更容易阅读,书写也更快速。缩进格式也可以使用 Sass 的全部功能,只是与 SCSS 相比个别地方采取了不同的表达方式
本案都是使用scss语法
/* scss 语法 */
.wrapper{
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
.inner{
width: 100px;
height: 100px;
background: linear-gradient(#6FB1AC,#5899BD);
&-text{
color: red;
}
}
}
/* sass 语法 */
body
widht: 100vw
height: 100vh
语法拓展
1、嵌套规则
Sass 允许将一套 CSS 样式嵌套进另一套样式中,内层的样式将它外层的选择器作为父选择器
嵌套功能避免了重复输入父选择器,而且令复杂的 CSS 结构更易于管理
1.1、html
<div class="wrapper">
<div class="inner"></div>
</div>
1.2、编译前的scss
/* 指定语言 scss */
<style lang="scss" scoped>
.wrapper{
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
.inner{
width: 100px;
height: 100px;
background: linear-gradient(#6FB1AC,#5899BD);
}
}
</style>
1.3、编译后的css
.wrapper {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.wrapper .inner {
width: 100px;
height: 100px;
background: linear-gradient(#6FB1AC, #5899BD);
}
1.4、效果
2、父选择器 &
&
后面的选择器会直接拼接在父选择器后面&
必须作为选择器的第一个字符,其后可以跟随后缀生成复合的选择器- 下面案例中,既能拼接类名
&-text
,又能拼接特殊的选择器&::first-letter
2.1、html
<div class="wrapper">
<div class="inner">
<p class="inner-text">Hello World</p>
</div>
</div>
2.2、编译前
.wrapper{
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
.inner{
width: 100px;
height: 100px;
background: linear-gradient(#6FB1AC,#5899BD);
&-text{
color: red;
&::first-letter{
font-weight: bold;
font-size: 16px;
color: blue;
}
}
}
}
2.2、编译后
.wrapper {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.wrapper .inner {
width: 100px;
height: 100px;
background: linear-gradient(#6FB1AC, #5899BD);
}
.wrapper .inner-text {
color: red;
}
.wrapper .inner-text::first-letter {
font-weight: bold;
font-size: 16px;
color: blue;
}
2.4、效果
3、属性嵌套
- 有些 CSS 属性遵循相同的命名空间 (namespace),比如
font-family, font-size, font-weight
都以font
作为属性的命名空间- 为了便于管理这样的属性,同时也为了避免了重复输入,Sass 允许将属性嵌套在命名空间中
3.1、编译前css
.inner-text{
font: {
weight: bold;
size: 24px
}
}
3.2、编译后css
.inner-text {
font-weight: bold;
font-size: 24px;
}
SassScript
在 CSS 属性的基础上 Sass 提供了一些名为 SassScript 的新功能。 SassScript 可作用于任何属性,允许属性使用变量、算数运算等额外功能。
1、变量
- SassScript 最普遍的用法就是变量,变量以美元符号($)开头,赋值方法与 CSS 属性的写法一样,使用
:
分割- 变量支持块级作用域,嵌套规则内定义的变量只能在嵌套规则内使用(局部变量),不在嵌套规则内定义的变量则可在任何地方使用(全局变量)
- 将局部变量转换为全局变量可以添加
!global
声明- sass的变量是在编译前就转换好,css的变量是在使用的时候,浏览器编译
注意:
- 变量名是不以数字开头的。可以包含
字母、数字、下划线、横线(连接符)
- 连接符(-)与下划线(_)定义的同名变量为同一变量,建议使用连接符
1.1、语法
// 定义变量
$label-width: 20px;
// 上面写法相当于 css的变量定义
--label-height: 20px;
// 使用变量
.inner{
width: $label-width;
height: var(--label-height)
}
1.2、html
<template>
<div class="wrapper">
<div class="inner-1">
inner-1
</div>
<div class="inner-2">
inner-2
</div>
</div>
</template>
1.3、编译前
.wrapper{
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
// scss 变量
$inner-width: 100px;
// css变量
--inner-height: 100px;
.inner-1{
// 局部,添加!global 变为全局
$inner-border: 1px solid #f39282 !global;
width: $inner-width;
height: var(--inner-height);
border: $inner-border;
}
.inner-2{
margin-left: 20px;
width: $inner-width;
height: var(--inner-height);
border: $inner-border;
}
}
1.4、编译后
.wrapper {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
--inner-height: 100px;
}
.wrapper .inner-1 {
width: 100px;
height: var(--inner-height);
border: 1px solid #f39282;
}
.wrapper .inner-2 {
margin-left: 20px;
width: 100px;
height: var(--inner-height);
border: 1px solid #f39282;
}
1.5、效果
1.6变量定义!default
- 可以在变量的结尾添加
!default
给一个未通过!default
声明赋值的变量赋值,此时,如果变量已经被赋值,不会再被重新赋值,但是如果变量还没有被赋值,则会被赋予新的值- 变量是 null 空值时将视为未被
!default
赋值。
1.1、编译前
.wrapper{
// scss 变量
$inner-width: 100px; // 使用这个
$inner-width: 200px !default; // 由于上面定义了这个变量,所以这个变量不会生效
// css变量
--inner-height: 100px;
--inner-height: 200px; // 使用这个
// 如果上面没有定义,则默认使用这个
$inner-border: 1px solid #f39282 !default;
.inner-1{
width: $inner-width;
height: var(--inner-height);
border: $inner-border;
}
.inner-2{
margin-left: 20px;
width: $inner-width;
height: var(--inner-height);
border: $inner-border;
}
}
1.2、编译后
.wrapper {
--inner-height: 100px;
--inner-height: 200px;
}
.wrapper .inner-1 {
width: 100px;
height: var(--inner-height);
border: 1px solid #f39282;
}
.wrapper .inner-2 {
margin-left: 20px;
width: 100px;
height: var(--inner-height);
border: 1px solid #f39282;
}
1.3、效果
2、数据类型
SassScript 支持 6 种主要的数据类型:
- 数字,
1, 2, 13, 10px
- 字符串,有引号字符串与无引号字符串,
"foo", 'bar', baz
- 颜色,
blue, #04a3f9, rgba(255,0,0,0.5)
- 布尔型,
true, false
- 空值,
null
- 数组 (list),用空格或逗号作分隔符,
1.5em 1em 0 2em, Helvetica, Arial, sans-serif
- maps, 相当于 JavaScript 的 object,
(key1: value1, key2: value2)
SassScript 也支持其他 CSS 属性值,比如 Unicode 字符集,或
!important
声明。然而Sass 不会特殊对待这些属性值,一律视为无引号字符串。
2.1、数字
2.1.1、编译前
// 数字
$heightAndWidth: 100px;
$domOpacity: .5;
.wrapper{
.inner-1{
width: $heightAndWidth;
height: $heightAndWidth;
border: 1px solid red;
opacity: $domOpacity;
}
}
2.1.2、编译后
.wrapper .inner-1 {
width: 100px;
height: 100px;
border: 1px solid red;
opacity: 0.5;
}
2.2、字符串
- SassScript 支持 CSS 的两种字符串类型:有引号字符串 (quoted strings),如
"Lucida Grande"
- 与无引号字符串 (unquoted strings),如
sans-serif
bold
,在编译 CSS 文件时不会改变其类型。- 只有一种情况例外,使用
#{}
(interpolation) 时,有引号字符串将被编译为无引号字符串(第五小节会讲)
2.2.1、编译前
.wrapper{
// 有引号字符串 与 无引号字符串
$fontFamaly: 'Courier New', Courier, monospace;
.inner-1{
font-family: $fontFamaly;
}
}
2.2.2、编译后
.wrapper .inner-1 {
font-family: "Courier New", Courier, monospace;
}
2.2.3、效果
2.3、数组
- 数组 (lists) 指 Sass 如何处理 CSS 中
margin: 10px 15px 0 0
或者font-face: Helvetica, Arial, sans-serif
这样通过空格或者逗号分隔的一系列的值。事实上,独立的值也被视为数组 —— 只包含一个值的数组。
2.3.1、编译前
// 数字
$heightAndWidth: 100px;
// 数组
$dom-border: 1px solid darkcyan;
// 数组
$dom-shadow: 2px 2px 3px rgba(0,0,0,.5);
.wrapper{
.inner-1{
width: $heightAndWidth;
height: $heightAndWidth;
border: $dom-border;
box-shadow: $dom-shadow;
}
}
2.3.2、编译后
.wrapper .inner-1 {
width: 100px;
height: 100px;
border: 1px solid darkcyan;
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
}
2.3.3、效果
2.4、颜色
2.4.1、编译前
// 数字
$heightAndWidth: 100px;
// 颜色
$dom-borderColor: rgb(112,159,123);
.wrapper{
.inner-1{
width: $heightAndWidth;
height: $heightAndWidth;
border: 1px solid $dom-borderColor;
}
}
2.4.2、编译后
.wrapper .inner-1 {
width: 100px;
height: 100px;
border: 1px solid rgb(112, 159, 123);
}
2.5、布尔值
- css中并没有值为布尔类型的样式
- 可以搭配
scss
的==控制指令(@if…等)==一起使用
2.5.1、编译前
// 数字
$heightAndWidth: 100px;
// 布尔
$flag: true;
.wrapper{
.inner-1{
width: $heightAndWidth;
height: $heightAndWidth;
border: 2px solid red;
@if $flag {
color: darkcyan;
}
@else {
color: fuchsia;
}
}
}
2.5.2、编译后
.wrapper .inner-1 {
width: 100px;
height: 100px;
border: 2px solid red;
color: darkcyan;
}
2.5.3、效果
2.6、空值
- null其类型的唯一值,它表示缺少值,通常由函数返回。以指示缺少结果
2.6.1、编译前
// 数字
$heightAndWidth: 100px;
// 数组
$marg: 1px 2px 2px 2px;
// 布尔
$var: null;
.wrapper{
.inner-1{
width: $heightAndWidth;
height: $heightAndWidth;
border: 2px solid red;
// 获取变量类型
content: type-of($heightAndWidth);
content: type-of($var);
// 获取变量长度
content: length($marg);
}
}
2.6.2、编译后
.wrapper .inner-1 {
width: 100px;
height: 100px;
border: 2px solid red;
content: number;
content: null;
content: 4;
}
2.7、maps
- 相当于
JavaScript
的Object(key1:val1,key2:val2)
- 使用
map-get(mapName,keyName)
获取值
2.7.1、编译前
// maps
$map: (heightAndWidth:100px, border:2px solid red);
.wrapper{
.inner-1{
width: map-get($map, heightAndWidth);
height: map-get($map, heightAndWidth);
border: map-get($map, border);
}
}
2.7.2、编译后
.wrapper .inner-1 {
width: 100px;
height: 100px;
border: 2px solid red;
}
3、运算
- 所有数据类型均支持相等运算
==
或!=
,此外,每种数据类型也有其各自支持的运算方式。
3.1、数字运算
- SassScript 支持数字的加减乘除、取整等运算 (
+, -, *, /, %
),如果必要会在不同单位间转换值。- 关系运算
<, >, <=, >=
也可用于数字运算,相等运算==, !=
可用于所有数据类型。
3.1.1、数学运算
// 编译前
.wrapper{
$heightAndWIdht: 50px;
.inner-1{
width: $heightAndWIdht+20px;
height: $heightAndWIdht+50px;
border: 1px+1px solid red;
}
}
// 编译后
.wrapper .inner-1 {
width: 70px;
height: 100px;
border: 2px solid red;
}
3.1.2、除法运算
/
在 CSS 中通常起到分隔数字的用途,SassScript 作为 CSS 语言的拓展当然也支持这个功能,同时也赋予了/
除法运算的功能。也就是说,如果/
在 SassScript 中把两个数字分隔,编译后的 CSS 文件中也是同样的作用。- 以下三种情况
/
将被视为除法运算符号:
- 如果值,或值的一部分,是变量或者函数的返回值
- 如果值被圆括号包裹
- 如果值是算数表达式的一部分
// 编译前
.wrapper{
$heightAndWIdht: 100px;
.inner-1{
// 编译报错 样式 写法 失效
font-size: 30px/3px;
// 值 使用变量 视为 除法
width: $heightAndWIdht/2;
// 值 被圆括号包裹 视为除法
height: (100px/2);
// 值 是算数表达的一部分 视为除法
border: 1px + 10px/10 solid red;
}
}
// 编译后
.wrapper .inner-1 {
font-size: 30px/3px;
width: 50px;
height: 50px;
border: 2px solid red;
}
3.2、颜色值运算
1.62.1版本目前不支持,编译报错
3.3、字符串运算
+
可用于连接字符串- 注意,如果有引号字符串==(位于
+
左侧)连接无引号字符串,运算结果是有引号的==,相反,无引号字符串(位于+
左侧)连接有引号字符串,运算结果则没有引号。- 运算表达式与其他值连用时,用空格做连接符
- 在有引号的文本字符串中使用
#{}
插值语句可以添加动态的值
3.3.1、编译前
.wrapper{
$heightAndWIdht: 100px;
.inner-1{
width: $heightAndWIdht/2;
height: (100px/2);
// 字符串运算
cursor: po + inter;
content: sans- + "serif";
font-family: 'Courier ' + New;
// 空格为连接符
margin: 10px - 1px auto;
// 在有引号的文本字符串中使用 #{} 插值语句可以添加动态的值
content: "i #{lo + ve} you"
}
}
3.3.2、编译后
.wrapper .inner-1 {
width: 50px;
height: 50px;
cursor: pointer;
content: sans-serif;
font-family: "Courier New";
margin: 9px auto;
content: "i love you";
}
4、圆括号
圆括号可以用来影响运算的顺序
4.1、编译前
.wrapper{
$heightAndWIdht: 100px;
.inner-1{
width: $heightAndWIdht/2;
height: (100px/2);
// 优先算 括号内的
font-size: 10em + (5em - 3) *2;
}
}
4.2、编译后
.wrapper .inner-1 {
width: 50px;
height: 50px;
font-size: 14em;
}
5、插值语句
- 通过
#{}
插值语句可以在选择器或属性名中使用变量
5.1、编译前
.wrapper{
$heightAndWIdht: 100px;
$name: inner-1;
$var: font;
.#{$name}{
width: $heightAndWIdht/2;
height: (100px/2);
// 优先算 括号内的
#{$var}-size: 10em + (5em - 3) *2;
}
}
5.2、编译后
.wrapper .inner-1 {
width: 50px;
height: 50px;
font-size: 14em;
}
@-Rules
Sass 支持所有的 CSS3 @-Rules,以及 Sass 特有的 “指令”(directives)
1、@import
- Sass 拓展了
@import
的功能,允许其导入 SCSS 或 Sass 文件。被导入的文件将合并编译到同一个 CSS 文件中- 被导入的文件中所包含的变量或者混合指令 (mixin) 都可以在导入的文件中使用
- 通常,
@import
寻找 Sass 文件并将其导入,但在以下情况下,@import
仅作为普通的 CSS 语句,不会导入任何 Sass 文件- 如果不在以下情况内,文件的拓展名是
.scss
或.sass
,则导入成功。没有指定拓展名,Sass 将会试着寻找文件名相同,拓展名为.scss
或.sass
的文件并将其导入
- 文件拓展名是
.css
- 文件名以
http://
开头- 文件名是
url()
@import
包含 media queries- 如果不在上述情况内,文件的拓展名是
.scss
或.sass
,则导入成功。没有指定拓展名,Sass 将会试着寻找文件名相同,拓展名为.scss
或.sass
的文件并将其导入。- Sass 允许同时导入多个文件
- 不可以在混合指令 (mixin) 或控制指令 (control directives) 中嵌套
@import
。
/* @import '@/assets/css/test2.scss'; 导入成功 */
// @import '@/assets/css/test2'; /* 含义同上 导入成功 */
// @import '@/assets/css/test2', '@/assets/css/test3'; /* 导入成功 */
// $urlfff: "family";
// @import url('http://fonts.googleapis.com/css?family=\#{$family}'); /* 导入成功 */
.wrapper{
@import '@/assets/css/test2'; /* 导入成功 */
}
2、@media
Sass 中
@media
指令与 CSS 中用法一样,只是增加了一点额外的功能
- 允许其在 CSS 规则中嵌套。如果
@media
嵌套在 CSS 规则内,编译时,@media
将被编译到文件的最外层,包含嵌套的父选择器- 这个功能让
@media
用起来更方便,不需要重复使用选择器,也不会打乱 CSS 的书写流程。@media
甚至可以使用 SassScript(比如变量,函数,以及运算符)代替条件的名称或者值
.wrapper {
width: 300px;
@media screen and (orientation: landscape) {
width: 500px;
}
}
// 编译为
.wrapper {
width: 300px;
}
@media screen and (orientation: landscape) {
.wrapper {
width: 500px;
}
}
// -------------------------------------------------------------------------
@media screen {
.wrapper {
@media (orientation: landscape) {
width: 500px;
}
}
}
// 编译为
@media screen and (orientation: landscape) {
.wrapper {
width: 500px;
}
}
// -------------------------------------------------------------------------
$media: screen;
$feature: -webkit-min-device-pixel-ratio;
$value: 1.5;
@media #{$media} and ($feature: $value) {
.wrapper {
width: 500px;
}
}
// 编译为
@media screen and (-webkit-min-device-pixel-ratio: 1.5) {
.wrapper {
width: 500px;
}
}
3、@extend
- 在编写代码的时候,我们样式统一的地方一般会写一个公共样式,如果个别地方会根据公共的样式,增加一些自己的样式,就会编写两个类名(一个公共样式的,一个自己独特的)
- 比如 如下案例:当前页面由很多标题,并且有很多样式一样,只不过标题颜色不同,那么我们肯定会把一样的样式,单独提取出来一个类名,然后在所有标题的标签类名上多添加一个
title
的类名,我们也可以使用如下方法,继承title
的样式
3.1、基本使用
3.1.1、修改前
html
<template>
<div class="wrapper">
<h2 class="title">标题1</h2>
<p>Lorem ipsum dolor sit amet.</p>
<h2 class="title t2">标题2</h2>
<p>Lorem ipsum dolor sit amet.</p>
<h2 class="title t3">标题3</h2>
<p>Lorem ipsum dolor sit amet.</p>
</div>
</template>
<style lang="scss" scoped>
.wrapper{
width: 100vw;
height: 100vh;
}
@import '@/assets/css/test.scss'; /* 导入成功 */
</style>
scss
.wrapper{
padding-left: 10px;
.title{
font-size: 18px;
display: flex;
align-items: center;
&::before{
content: '';
display: inline-block;
width: 2px;
height: 23px;
background-color: darkcyan;
margin-right: 10px;
}
}
.t2{
color: red;
}
.t3{
color: blue;
}
}
3.1.2、修改后
html
去掉了重复的类名使用 title
<template>
<div class="wrapper">
<h2 class="title">标题1</h2>
<p>Lorem ipsum dolor sit amet.</p>
<h2 class="t2">标题2</h2>
<p>Lorem ipsum dolor sit amet.</p>
<h2 class="t3">标题3</h2>
<p>Lorem ipsum dolor sit amet.</p>
</div>
</template>
<style lang="scss" scoped>
.wrapper{
width: 100vw;
height: 100vh;
}
@import '@/assets/css/test.scss'; /* 导入成功 */
</style>
scss
在每个使用到
title
的样式里,使用@extend .title;
继承.title
的样式
.wrapper{
padding-left: 10px;
.title{
font-size: 18px;
display: flex;
align-items: center;
&::before{
content: '';
display: inline-block;
width: 2px;
height: 23px;
background-color: darkcyan;
margin-right: 10px;
}
}
.t2{
@extend .title;
color: red;
}
.t3{
@extend .title;
color: blue;
}
}
3.1.3、编译后
.wrapper {
padding-left: 10px;
}
.wrapper .title, .wrapper .t3, .wrapper .t2 {
font-size: 18px;
display: flex;
align-items: center;
}
.wrapper .title::before, .wrapper .t3::before, .wrapper .t2::before {
content: "";
display: inline-block;
width: 2px;
height: 23px;
background-color: darkcyan;
margin-right: 10px;
}
.wrapper .t2 {
color: red;
}
.wrapper .t3 {
color: blue;
}
3.1.4、注意
- 其他使用到
.title
的样式也会同样继承给.t2 .t3
,例如,另一个样式.title.border
使用了border
属性- 那么,如果继承的标签上,也有类名
border
,则同样会应用样式
html
<template>
<div class="wrapper">
<h2 class="title">标题1</h2>
<p class="p1">Lorem ipsum dolor sit amet.</p>
<h2 class="title border">带边框的标题1</h2>
<p class="p2">Lorem ipsum dolor sit amet.</p>
<h2 class="t2 border">标题2</h2>
<p class="p3">Lorem ipsum dolor sit amet.</p>
<h2 class="t3">标题3</h2>
<p class="p4">Lorem ipsum dolor sit amet.</p>
</div>
</template>
<style lang="scss" scoped>
.wrapper{
width: 100vw;
height: 100vh;
}
@import '@/assets/css/test.scss'; /* 导入成功 */
</style>
scss编译前
.wrapper{
padding-left: 10px;
.title{
font-size: 18px;
display: flex;
align-items: center;
&::before{
content: '';
display: inline-block;
width: 2px;
height: 23px;
background-color: darkcyan;
margin-right: 10px;
}
&.border{
border: 3px solid darkkhaki
}
}
// 等效于上面内联语法
/* .title.border{
border: 3px solid darkkhaki
} */
.t2{
@extend .title;
color: red;
}
.t3{
@extend .title;
color: blue;
}
}
scss编译后
.wrapper {
padding-left: 10px;
/* .title.border{
border: 3px solid darkkhaki
} */
}
.wrapper .title, .wrapper .t3, .wrapper .t2 {
font-size: 18px;
display: flex;
align-items: center;
}
.wrapper .title::before, .wrapper .t3::before, .wrapper .t2::before {
content: "";
display: inline-block;
width: 2px;
height: 23px;
background-color: darkcyan;
margin-right: 10px;
}
.wrapper .title.border, .wrapper .border.t3, .wrapper .border.t2 {
border: 3px solid darkkhaki;
}
.wrapper .t2 {
color: red;
}
.wrapper .t3 {
color: blue;
}
效果
因为最后一个标题,类名中,没有
border
,所以样式没有匹配到,所以没有应用边框
3.2、延伸复杂的选择器
- Class 选择器并不是唯一可以被延伸 (extend) 的,Sass 允许延伸任何定义给单个元素的选择器,比如
.special.cool
,a:hover
- 1.62.1:版本不支持,编译报错(下面为官网案例)
.hoverlink {
@extend a:hover;
}
a:hover {
text-decoration: underline;
}
// 编译后
a:hover, .hoverlink {
text-decoration: underline;
}
3.3、多重延伸
- 同一个选择器可以延伸给多个选择器,它所包含的属性将继承给所有被延伸的选择器
- 虽然两个
border
都被编译出来了,但是由于第二个border是后继承的,后定义的样式享有优先权,所以值还是取2px solid red
// 编译前
.wrapper{
padding-left: 10px;
.title{
font-size: 18px;
display: flex;
align-items: center;
border: 1px solid green;
}
.tit{
border: 2px solid red;
}
.t2{
@extend .title;
@extend .tit;
color: red;
}
}
// 编译后
.wrapper {
padding-left: 10px;
}
.wrapper .title, .wrapper .t2 {
font-size: 18px;
display: flex;
align-items: center;
border: 1px solid green;
}
.wrapper .tit, .wrapper .t2 {
border: 2px solid red;
}
.wrapper .t2 {
color: red;
}
多重延伸可以使用逗号分隔选择器名,上面的sass代码,可以写为如下格式
.wrapper{
padding-left: 10px;
.title{
font-size: 18px;
display: flex;
align-items: center;
border: 1px solid green;
}
.tit{
border: 2px solid red;
}
.t2{
@extend .title, .tit;
color: red;
}
}
3.4、继续延伸
当一个选择器延伸给第二个后,可以继续将第二个选择器延伸给第三个
3.4.1、编译前
// 编译前
.wrapper{
padding-left: 10px;
.title{
font-size: 18px;
display: flex;
align-items: center;
border: 1px solid green;
}
.t2{
@extend .title;
color: red;
}
.t3{
@extend .t2;
}
}
3.4.2、编译后
// 编译后
.wrapper {
padding-left: 10px;
}
.wrapper .title, .wrapper .t2, .wrapper .t3 {
font-size: 18px;
display: flex;
align-items: center;
border: 1px solid green;
}
.wrapper .t2, .wrapper .t3 {
color: red;
}
3.5、@extend-Only 选择器
- 有时,需要定义一套样式并不是给某个元素用,而是只通过
@extend
指令使用,尤其是在制作 Sass 样式库的时候,希望 Sass 能够忽略用不到的样式。- 如果使用普通的 CSS 规则,最后会编译出很多用不到的样式,也容易与其他样式名冲突,所以,Sass 引入了“占位符选择器” (placeholder selectors)
- 看起来很像普通的
id
或class
选择器,只是#
或.
被替换成了%
。可以像 class 或者 id 选择器那样使用,当它们单独使用时,不会被编译到 CSS 文件中
3.5.1、定义
.wrapper .a%extendName{
background-color: aqua;
}
3.5.2、使用
.title{
@extend %extendName;
color: red;
}
3.5.3、编译后
.wrapper .a.title {
background-color: aqua;
}
.title {
color: red;
}
3.6、在指令中延伸
- 在指令中使用
@extend
时(比如在@media
中)有一些限制:Sass 不可以将@media
层外的 CSS 规则延伸给指令层内的 CSS,这样会生成大量的无用代码- 也就是说,如果在
@media
(或者其他 CSS 指令)中使用@extend
,必须延伸给相同指令层中的选择器
3.6.1、成功的例子
@media print {
.error {
border: 1px #f00;
background-color: #fdd;
}
.seriousError {
@extend .error;
border-width: 3px;
}
}
3.6.2、失败的例子
.error {
border: 1px #f00;
background-color: #fdd;
}
@media print {
.seriousError {
// 不可以继承指令@media 外的样式
@extend .error;
border-width: 3px;
}
}
4、@at-root
- @at-root指令导致一个或多个规则在文档的根处发出,而不是嵌套在其父选择器下
- 它可以与单个内联选择器一起使用
4.1、编译前
.parent {
...
@at-root {
.child1 { ... }
.child2 { ... }
}
.step-child { ... }
}
4.2、编译后
.parent { ... }
.child1 { ... }
.child2 { ... }
.parent .step-child { ... }
- 默认
@at-root
只能排除选择器,但是,也可以使用@at-root
在根目录下移动到嵌套指令(如@media)之外
4.3、编译前
@media print {
.page {
width: 8in;
@at-root (without: media) {
color: red;
}
}
}
4.4、编译后
@media print {
.page {
width: 8in;
}
}
.page {
color: red;
}
控制指令
SassScript 提供了一些基础的控制指令,比如在满足一定条件时引用样式,或者设定范围重复输出格式。控制指令是一种高级功能,日常编写过程中并不常用到,主要与混合指令 (mixin) 配合使用,尤其是用在 Compass 等样式库中
1、@if
当
@if
的表达式返回值不是false
或者null
时,条件成立,输出{}
内的代码
1.1、编译前
p {
@if 1 + 1 == 2 { border: 1px solid; }
@if 5 < 3 { border: 2px dotted; }
@if null { border: 3px double; }
}
1.2、编译后
p {
border: 1px solid;
}
@if
声明后面可以跟多个@else if
声明,或者一个@else
声明。- 如果
@if
声明失败,Sass 将逐条执行@else if
声明,如果全部失败,最后执行@else
声明
1.3、编译前
$type: monster;
p {
@if $type == ocean {
color: blue;
} @else if $type == matador {
color: red;
} @else if $type == monster {
color: green;
} @else {
color: black;
}
}
1.4、编译后
p {
color: green;
}
2、@for
@for
指令可以在限制的范围内重复输出格式,每次按要求(变量的值)对输出结果做出变动。- 这个指令包含两种格式
@for $var from <start> through <end>{...}
@for $var from <start> to <end>{...}
- 区别在于
through
与to
的含义:当使用through
时,条件范围包含<start>
与<end>
的值- 而使用
to
时条件范围只包含<start>
的值不包含<end>
的值(左闭右开)- 另外,
$var
可以是任何变量,比如$i
;<start>
和<end>
必须是整数值。
2.1、编译前
@for $i from 1 through 5{
.inner-#{$i}{
background: rgba(random(255), random(255), random(255), 0.8);
}
}
2.2、编译后
.wrapper .inner-1 {
background: rgba(112, 37, 127, 0.8);
}
.wrapper .inner-2 {
background: rgba(76, 227, 87, 0.8);
}
.wrapper .inner-3 {
background: rgba(248, 174, 69, 0.8);
}
.wrapper .inner-4 {
background: rgba(216, 12, 153, 0.8);
}
.wrapper .inner-5 {
background: rgba(161, 164, 210, 0.8);
}
3、@each
@each
指令的格式是$var in <list>{...}
,$var
可以是任何变量名,- 比如
$length
或者$name
,而<list>
是一连串的值,也就是值列表
3.1、编译前
// 单属性列表 list
@each $animal in puma, sea-slug, egret, salamander {
.#{$animal}-icon {
background-image: url('/images/#{$animal}.png');
}
}
// 多属性列表 list
@each $animal, $color, $cursor in (puma, black, default),
(sea-slug, blue, pointer),
(egret, white, move) {
.#{$animal}-icon {
background-image: url('/images/#{$animal}.png');
border: 2px solid $color;
cursor: $cursor;
}
}
// map列表
@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) {
#{$header} {
font-size: $size;
}
}
3.2、编译后
/* 单属性列表 */
.puma-icon {
background-image: url('/images/puma.png');
}
.sea-slug-icon {
background-image: url('/images/sea-slug.png');
}
.egret-icon {
background-image: url('/images/egret.png');
}
.salamander-icon {
background-image: url('/images/salamander.png');
}
/* 多属性列表 */
.puma-icon {
background-image: url('/images/puma.png');
border: 2px solid black;
cursor: default;
}
.sea-slug-icon {
background-image: url('/images/sea-slug.png');
border: 2px solid blue;
cursor: pointer;
}
.egret-icon {
background-image: url('/images/egret.png');
border: 2px solid white;
cursor: move;
}
/* map列表 */
h1 {
font-size: 2em;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.2em;
}
4、@while
@while
指令重复输出格式直到表达式返回结果为false
。这样可以实现比@for
更复杂的循环,只是很少会用到
4.1、编译前
$i: 6;
@while $i > 0 {
.item-#{$i} {
width: 2em * $i;
}
$i: $i - 2;
}
4.2、编译后
.item-6 {
width: 12em;
}
.item-4 {
width: 8em;
}
.item-2 {
width: 4em;
}
混合指令
- 混合指令(Mixin)用于定义可重复使用的样式,避免了使用无语意的 class,
- 比如
.float-left
。混合指令可以包含所有的 CSS 规则,绝大部分 Sass 规则,甚至通过参数功能引入变量,输出多样化的样式。
1、定义混合指令@mixin
- 混合指令的用法是在
@mixin
后添加名称与样式,比如名为large-text
的混合通过下面的代码定义- 混合也需要包含选择器和属性,甚至可以用
&
引用父选择器:
语法
@mixin clearfix {
display: inline-block;
&:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
}
2、引用混合样式@include
使用
@include
指令引用混合样式,格式是在其后添加混合名称,以及需要的参数(可选)
2.1、语法
.wrapper{
@include clearfix;
}
2.2、编译后
.wrapper {
display: inline-block;
}
.wrapper:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
* html .wrapper {
height: 1px;
}
也可以在最外层引用混合样式,不会直接定义属性,也不可以使用父选择器。
2.3、编译前
@mixin silly-links {
a {
color: blue;
background-color: red;
}
}
@include silly-links;
2.4、编译后
a {
color: blue;
background-color: red;
}
混合样式中也可以包含其他混合样式
2.5、语法
@mixin compound {
@include highlighted-background;
@include header-text;
}
@mixin highlighted-background { background-color: #fc0; }
@mixin header-text { font-size: 20px; }
3、带参
- 参数用于给混合指令中的样式设定变量,并且赋值使用
- 在定义混合指令的时候,按照变量的格式,通过逗号分隔,将参数写进圆括号里
- 引用指令时,按照参数的顺序,再将所赋的值对应写进括号
3.1、简单使用
3.1.1、编译前
@mixin sexy-border($color, $width) {
border: {
color: $color;
width: $width;
style: dashed;
}
}
p {
@include sexy-border(blue, 1in)
};
3.1.2、编译后
p {
border-color: blue;
border-width: 1in;
border-style: dashed;
}
3.2、赋默认值
混合指令也可以使用给变量赋值的方法给参数设定默认值,然后,当这个指令被引用的时候,如果没有给参数赋值,则自动使用默认值
3.2.1、编译前
@mixin sexy-border($color, $width: 1in) {
border: {
color: $color;
width: $width;
style: dashed;
}
}
p {
@include sexy-border(blue);
}
h1 {
@include sexy-border(blue, 2in);
}
3.2.2、编译后
p {
border-color: blue;
border-width: 1in;
border-style: dashed;
}
h1 {
border-color: blue;
border-width: 2in;
border-style: dashed;
}
3.3、关键词参数
混合指令也可以使用关键词参数,上面的例子也可以写成
- 关键词参数可以打乱顺序使用,如果使用默认值也可以省缺
- 参数名被视为变量名,下划线、短横线可以互换使用。
p {
@include sexy-border($color: blue);
}
h1 {
@include sexy-border($color: blue, $width: 2in);
}
3.4、参数变量
- 有时,不能确定混合指令需要使用多少个参数
- 比如一个关于
box-shadow
的混合指令不能确定有多少个 ‘shadow’ 会被用到。- 这时,可以使用参数变量
…
声明(写在参数的最后方)告诉 Sass 将这些参数视为值列表处理
3.4.1、编译前
@mixin box-shadow($shadows...) {
-moz-box-shadow: $shadows;
-webkit-box-shadow: $shadows;
box-shadow: $shadows;
}
.shadows {
@include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
}
3.4.2、编译后
.shadowed {
-moz-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
-webkit-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
}
参数变量也可以用在引用混合指令的时候 (
@include
),与平时用法一样,将一串值列表中的值逐条作为参数引用
3.4.3、编译前
@mixin colors($text, $background, $border) {
color: $text;
background-color: $background;
border-color: $border;
}
$values: #ff0000, #00ff00, #0000ff;
.primary {
@include colors($values...);
}
3.4.4、编译后
.primary {
color: #ff0000;
background-color: #00ff00;
border-color: #0000ff;
}
4、向混合样式中导入内容
在引用混合样式的时候,可以先将一段代码导入到混合指令中,然后再输出混合样式,额外导入的部分将出现在
@content
标志的地方
4.1、编译前
@mixin apply-to-ie6-only {
* html {
@content;
}
}
@include apply-to-ie6-only {
#logo {
background-image: url(/logo.gif);
}
}
4.2、编译后
* html #logo {
background-image: url(/logo.gif);
}
函数指令
Sass 支持自定义函数,并能在任何属性值或 Sass script 中使用
1、定义函数
$grid-width: 40px;
$gutter-width: 10px;
@function grid-width($n) {
// 5 * 40 + (5-1) * 10 = 240
@return $n * $grid-width + ($n - 1) * $gutter-width;
}
2、使用函数
#sidebar {
width: grid-width(5);
}
3、编译后
#sidebar {
width: 240px;
}
内置函数
更多内置函数查看官网:Sass: sass:color (sass-lang.com)
1、random
- 当没有传参时(默认为null):返回一个介于0和1之间的随机十进制数。
- random()忽略 l i m i t 中的单位。此行为已被弃用, r a n d o m ( limit中的单位。此行为已被弃用,random( limit中的单位。此行为已被弃用,random(limit)将返回一个与$limit参数具有相同单位的随机整数。
1.1、语法
math.random($limit: null)
random($limit: null) //=> number
1.2、随机生成颜色
- 只有每次重新编译才会生成
.wrapper{
background-color: rgb(random(255), random(255), random(255));
}