sass学习归纳总结笔记
一,sass简介
Sass 预处理器是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,这些拓展令 CSS 更加强大与优雅。——官方介绍
完全兼容 CSS3
在 CSS 基础上增加变量、嵌套 (nesting)、混合 (mixins) 等功能
通过函数进行颜色值与属性值的运算
提供控制指令 (control directives)等高级功能
自定义输出格式
1,SCSS和SASS的关系
sass和scss其实是一种css预处理语言,只是语法格式有所不同。
SCSS 是 Sass 3 引入新的语法,sass为Sass3之前版本的语法
任何一种格式可以直接导入(@import) 到另一种格式中使用,或者通过 sass-convert 命令行工具转换成另一种格式
继sass之后scss的编写规范基本和css一致,sass时代是有严格的缩进规范并且没有‘{}’和‘;等
sass
是最早的sass语法格式,被称为缩进格式 (Indented Sass) 通常简称 "Sass",是一种简化格式。它使用 “缩进” 代替 “花括号” 表示属性属于某个选择器,用 “换行” 代替 “分号” 分隔属性,很多人认为这样做比 SCSS 更容易阅读,书写也更快速。缩进格式也可以使用 Sass 的全部功能,只是与 SCSS 相比个别地方采取了不同的表达方式
scss
SCSS 是 Sass 3 引入新的语法,其语法完全兼容 CSS3,并且继承了 Sass 的强大功能。也就是说,任何标准的 CSS3 样式表都是具有相同语义的有效的 SCSS 文件。SCSS 需要使用分号和花括号而不是换行和缩进。SCSS 对空白符号不敏感,其实就和css3语法一样,其后缀名是可以为.scss和.sass
SCSS 和 CSS 写法无差别,把你现有的“.css”文件直接修改成“.scss”仍可使用。
//示例 // sass #root width: 30% background-color: #faa // scss #root { width: 30%; background-color: #faa; }复制代码
所以说推荐使用scss,下面内容皆为scss语法格式
2,CSS常见预处理器介绍
1. SCSS/SASS
SASS (.scss)。于2007年诞生,最早也是最成熟的CSS预处理器,拥有ruby社区的支持和compass这一最强大的css框架,目前受LESS影响,已经进化到了全面兼容CSS的SCSS。文件以.sass结尾
2. LESS
LESS (.less)。于2009年诞生,借鉴了SASS的长处,并兼容了CSS语法,使得开发者使用起来更为方便顺手,但是相比于SASS,其编程功能不够丰富,反而促使SASS进化成为了SCSS。
3. Stylus
Stylus (.styl)。于2010年诞生,出自Node.js社区,主要用来给Node项目进行CSS预处理支持,人气较前两者偏低。
二,环境配置
less、scss(sass)和stylus代码并不能被浏览器直接解析,所以必须先将它们编译成css代码
1,安装
这里使用简单且实用的方式——使用vscode安装扩展两个Easy Sass(编译)和Sass(代码提示)来完成环境的简单搭建。
2,配置
在设置中找到settings.json全局配置文件添加如下内容
"easysass.compileAfterSave": true, // 保存scss/sass文件后自动编译 // 编译不同格式的css "easysass.formats": [ { "format": "expanded", "extension": ".css" }, { "format": "compressed", "extension": ".min.css" } ], //1,format可选参数 // 参数值默认是expanded(没有缩进的、扩展的css代码) // compact:简洁格式的 css 代码,每个选择器的全部样式写在同一行。 // compressed:压缩后的 css 代码。 // 2.easysass.formats[i].extension 用以设置编译输出的文件拓展名,此处可以自定义文件名,输出的 css 文件名会按照“当前 Sass 文件名(不含拓展名)+此处自定义文件名”的格式来生成 // 例如:设置 ".min.css",假设当前的 Sass 文件名为style.scss,则编译输出的 css 文件名为 style.min.css "easysass.targetDir": "" // 很多情况下 scss/sass 文件和 css 文件是不在同一个目录下的,而 Easy Sass 默认输出的 css 是和当前 Sass 文件处于相同目录的为此我们需要通过该参数来配置输出路径复制代码
测试:创建a.scss文件,写入一些样式,保存便会自动编译出两个如下文件
-----text | --a.scss | --a.css | --a.min.css 复制代码
三,核心语法
1,变量
[1] 变量声明
$符定义 $width: 1600px; $pen-size: 3em;复制代码
[2]使用变量
直接使用变量的名称即可调用变量
#app { height: $width; font-size: $pen-size; }复制代码
[3]作用域
在样式内部定义的变量默认文局部变量,只能在其内部使用,将局部变量转换为全局变量可以添加 !global
声明
#foo { $width: 5em !global; width: $width; } #bar { width: $width; }复制代码
编译后:
#foo { width: 5em; } #bar { width: 5em; }复制代码
还有推荐使用下划线命名法
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 不会特殊对待这些属性值,一律视为无引号字符串。
判断数据类型的方式:type-of($value)
[1].字符串 (Strings)
SassScript 支持 CSS 的两种字符串类型:有引号字符串 (quoted strings)
,和无引号字符串 (unquoted strings)
。
$name: 'Tom Bob'; $container: "top bottom"; $what: heart; //引号也会被编译成引号 // 注:在编译 CSS 文件时不会改变其类型。只有一种情况例外,使用 `#{}` (interpolation) 时,有引号字符串将被编译为无引号字符串,这样便于在 mixin 中引用选择器名复制代码
[2],空值(Null)
只有一个取值null
$value: null; // 注:由于它代表空,所以不能够使用它与任何类型进行算数运算复制代码
[3],布尔型(Booleans)
只有两个取值:true
和false
$a: true; $b: false; // 注:只有自身是false和null才会返回false,其他一切都将返回true复制代码
[4].数组 (Lists)
通过空格
或者逗号
分隔的一系列的值。事实上,独立的值也被视为数组 —— 只包含一个值的组。索引从1
开始
$list0: 1px 2px 5px 6px; $list1: 1px 2px, 5px 6px; //数组中包两个含子数组(用逗号隔开) $list2: (1px 2px) (5px 6px); //数组中包含子两数组(用括号隔开)复制代码
当数组被编译为 CSS 时,Sass 不会添加任何圆括号(CSS 中没有这种写法),所以 (1px 2px) (5px 6px)
与 1px 2px, 5px 6px
在编译后的 CSS 文件中是完全一样的,但是它们在 Sass 文件中却有不同的意义,前者是包含两个数组的数组,而后者是包含四个值的数组。
用 ()
表示不包含任何值的空数组(在 Sass 3.3 版之后也视为空的 map)。空数组不可以直接编译成 CSS,比如编译 font-family: ()
Sass 将会报错。如果数组中包含空数组或空值,编译时将被清除,比如 1px 2px () 3px
或 1px 2px null 3px
。
基于逗号分隔的数组允许保留结尾的逗号,这样做的意义是强调数组的结构关系,尤其是需要声明只包含单个值的数组时。例如 (1,)
表示只包含 1
的数组,而 (1 2 3,)
表示包含 1 2 3
这个以空格分隔的数组的数组。
[5].Maps
Maps必须被圆括号包围,可以映射任何类型键值对(任何类型,包括内嵌maps,不过不推荐这种内嵌方式)
$map: ( $key1: value1, $key2: value2, $key3: value3 )复制代码
[6].颜色 (Colors)
CSS原有颜色类型,十六进制、RGB、RGBA、HSL、HSLA和色彩单词
SCSS提供了内置Colors函数,从而更方便地使用颜色
$color0: green; $color1: lighten($color, 15%); $color2: darken($color, 15%); $color3: saturate($color, 15%); $color4: desaturate($color, 15%); $color5: (green + red); $color6:rgb(#f3e1e1,0.3);rgb值加透明度在css中是不能这样写的,这里编译后就转为rgb值了复制代码
3,运算
所有数据类型均支持相等运算 ==
或 !=
,此外,每种数据类型也有其各自支持的运算方式。
[1],数字运算
SassScript 支持数字的加减乘除、取整等运算 (+, -, *, /, %
),如果必要会在不同单位间转换值
如果要保留运算符号,则应该使用插值语法
+
// 纯数字 $add1: 1 + 2; // 3 $add2: 1 + 2px; // 3px $add3: 1px + 2; // 3px $add4: 1px + 2px;//3px // 纯字符串 $add5: "a" + "b"; // "ab" $add6: "a" + b; // "ab" $add7: a + "b"; // ab $add8: a + b; // ab // 数字和字符串 $add9: 1 + a; // 1a $adda: a + 1; // a1 $addb: "1" + a; // "1a" $addc: 1 + "a"; // "1a" $addd: "a" + 1; // "a1" $adde: a + "1"; // a1 $addf: 1 + "1"; // "11"复制代码
// 总结: a.纯数字:只要有单位,结果必有单位 b.纯字符串:第一个字符串有无引号决定结果是否有引号 c数字和字符串:第一位有引号,结果必为引号;第一位对应数字非数字且最后一位带有引号,则结果必为引号复制代码
-
$add1: 1 - 2; // -1 $add2: 1 - 2px; // -1px $add3: 1px - 2; // -1px $add4: 1px - 2px;//-1px $sub1: a - 1; // a-1 $sub2: 1 - a; // 1-a $sub3: "a" - 1;// "a"-1 $sub4: a - "1";// a-"1"复制代码
// 总结: 每个字段必须前部分为数字,且两个字段只能一个后部分是字符(因为此时后缀被当被单位看待了)。 只要其中一个值首位不为数字的,结果就按顺序去除空格后拼接起来复制代码
*
$num1: 1 * 2; // 2 $mul2: 1 * 2px; // 2px $num3: 1px * 2; // 2px $num4: 2px * 2px;// 编译不通过 $num5: 1 * 2abc; // 2abc复制代码
// 总结: 每个字段必须前部分为数字,且两个字段只能一个后部分是字符(因为此时后缀被当被单位看待了)。其余编译不通过复制代码
/
// 总结: a.不会四舍五入,精确到小数点后5位 b.每个字段必须前部分为数字,且当前者只是单纯数字无单位时,后者(除数)后部分不能有字符。其余结果就按顺序去除空格后拼接起来。 (因为此时后缀被当被单位看待了)复制代码
%
// 总结: a.值与"%"之间必须要有空格,否则会被看做字符串复制代码
[2],关系运算符
同JavaScript。。。。。
[3].布尔运算符
SassScript 支持布尔型的 and
or
以及 not
运算。
[4],颜色值运算(不常用)
颜色值的运算是分段计算进行的,也就是分别计算红色,绿色,以及蓝色的值:
p { color: #010203 + #040506; }复制代码
计算 01 + 04 = 05
02 + 05 = 07
03 + 06 = 09
,然后编译为
p { color: #050709; }复制代码
使用 color functions 比计算颜色值更方便一些。
数字与颜色值之间也可以进行算数运算,同样也是分段计算的,比如
p { color: #010203 * 2; }复制代码
计算 01 * 2 = 02
02 * 2 = 04
03 * 2 = 06
,然后编译为
p { color: #020406; }复制代码
需要注意的是,如果颜色值包含 alpha channel(rgba 或 hsla 两种颜色值),必须拥有相等的 alpha 值才能进行运算,因为算术运算不会作用于 alpha 值。
p { color: rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75); }复制代码
编译为
p { color: rgba(255, 255, 0, 0.75); }复制代码
颜色值的 alpha channel 可以通过 opacify 或 transparentize 两个函数进行调整。
$translucent-red: rgba(255, 0, 0, 0.5); p { color: opacify($translucent-red, 0.3); background-color: transparentize($translucent-red, 0.25); }复制代码
编译为
p { color: rgba(255, 0, 0, 0.8); background-color: rgba(255, 0, 0, 0.25); }复制代码
IE 滤镜要求所有的颜色值包含 alpha 层,而且格式必须固定 #AABBCCDD
,使用 ie_hex_str
函数可以很容易地将颜色转化为 IE 滤镜要求的格式。
$translucent-red: rgba(255, 0, 0, 0.5); $green: #00ff00; div { filter: progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#{ie-hex-str($green)}', endColorstr='#{ie-hex-str($translucent-red)}'); }复制代码
编译为
div { filter: progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr=#FF00FF00, endColorstr=#80FF0000); }复制代码
[5], 圆括号 (Parentheses)
圆括号可以用来影响运算的优先级:
p { width: 1em + (2em * 3); }复制代码
编译为
p { width: 7em; }复制代码
补充:运算优先级同js
[6],字符串运算
+
可用于连接字符串
p { cursor: e + -resize; }复制代码
编译为
p { cursor: e-resize; }复制代码
注意,如果有引号字符串(位于 +
左侧)连接无引号字符串,运算结果是有引号的,相反,无引号字符串(位于 +
左侧)连接有引号字符串,运算结果则没有引号。
p:before { content: "Foo " + Bar; font-family: sans- + "serif"; }复制代码
编译为
p:before { content: "Foo Bar"; font-family: sans-serif; }复制代码
运算表达式与其他值连用时,用空格做连接符:
p { margin: 3px + 4px auto; }复制代码
编译为
p { margin: 7px auto; }复制代码
在有引号的文本字符串中使用 #{}
插值语句可以添加动态的值:
p:before { content: "I ate #{5 + 10} pies!"; }复制代码
编译为
p:before { content: "I ate 15 pies!"; }复制代码
空的值被视作插入了空字符串:
$value: null; p:before { content: "I ate #{$value} pies!"; }复制代码
编译为
p:before { content: "I ate pies!"; }复制代码
4,嵌套规则(常用)
在sass写样式可以像写dom时一样嵌套的去写
<body> <div id="app"> <span>哈哈哈哈</span> <div class="front"> <a href="#"></a> </div> </div> </body>复制代码
#app { span { color:red; } .front { a { margin:0; padding:0; } #app aside{....}//这样也是可以的 } }复制代码
#app span { color: red; } #app .front a { margin: 0; padding: 0; }复制代码
[1],父选择器的标识符&
一般情况下,sass
在解开一个嵌套规则时就会把父选择器(#app
)通过一个空格连接到子选择器的前边(span
和.font a
)形成(#content span
和#content front a
)。这种在CSS里边被称为后代选择器,因为它选择ID为app
的元素内所有命中选择器span
和.front a
的元素。但在有些情况下你却不会希望sass
使用这种后代选择器的方式生成这种连接。
最常见的一种情况是当你为链接之类的元素写:hover
这种伪类时,你并不希望以后代选择器的方式连接。
article a { color: blue; :hover { color: red } }复制代码
由scss其解开嵌套的规则,上面代码就会无法编译。因为伪类选择器在与被选中元素之间是没有空格的,而使用sccs嵌套规则解开后是有空格的。
/* 要编译成这样才才符合css中伪类选择器的规则 */ article a:hover { color: red; }复制代码
这意味着color: red
这条规则将会被应用到选择器article a :hover
,article
元素内链接的所有子元素在被hover
时都会变成红色。这是不正确的!你想把这条规则应用到超链接自身,而后代选择器的方式无法帮你实现。
那么这么解决这个问题,&标识符出现了。有了&标识符,在使用嵌套规则时,父选择器能对于嵌套规则如何解开提供更好的控制,&可以放在任何一个选择器可出现的地方
article a { color: blue; &:hover { color: red } }复制代码
当包含父选择器标识符的嵌套规则被打开时,它不会像后代选择器那样进行拼接,而是&
被父选择器直接替换:
article a { color: blue } article a:hover { color: red }复制代码
在为父级选择器添加:hover
等伪类时,这种方式非常有用。
同时父选择器标识符还有另外一种用法,你可以在父选择器之前添加选择器。举例来说,当用户在使用IE浏览器时,你会通过JavaScript
在<body>
标签上添加一个ie的类名,为这种情况编写特殊的样式如下:
#content aside { color: red; body.ie & { color: green } } /*编译后*/ #content aside {color: red}; body.ie #content aside { color: green }复制代码
sass
在选择器嵌套上是非常智能的,即使是带有父选择器的情况。当sass
遇到群组选择器(由多个逗号分隔开的选择器形成)也能完美地处理这种嵌套
[2],群选择器的嵌套
群选择器
.button, button { margin: 0; } 群组选择器 的规则会对命中群组中任何一个选择器的元素生效复制代码
出现的问题
重复性的工作会增加,如下
.container h1, .container h2, .container h3 { margin-bottom: .8em }复制代码
scss的解决方式
.container { h1, h2, h3 {margin-bottom: .8em} } 这种写法编译后将成为上面的复制代码
更多不同情况的实例
nav, aside { a {color: blue} } 编译后 nav a, aside a {color: blue}复制代码
处理这种群组选择器规则嵌套上的强大能力,正是sass
在减少重复敲写方面的贡献之一。尤其在当嵌套级别达到两层甚至三层以上时,与普通的css
编写方式相比,只写一遍群组选择器大大减少了工作量。
有利必有弊,你需要特别注意群组选择器的规则嵌套生成的css
。虽然sass
让你的样式表看上去很小,但实际生成的css
却可能非常大,这会降低网站的速度。
[3],子组合选择器和同层组合选择器:>、+和~;
关于选择器嵌套的最后一个方面,我们看看sass
如何处理组合选择器,比如>、+和~的使用。你将看到,这种场景下你甚至无需使用父选择器标识符。
子组合选择器:“>”
article section { margin: 5px } article > section { border: 1px solid #ccc }复制代码
你可以用子组合选择器>选择一个元素的直接子元素。上例中,第一个选择器会选择article下的所有命中section选择器的元素。第二个选择器只会选择article下紧跟着的子元素中命中section选择器的元素。
其实是同css的子选择器规则的
相邻组合选择器:“+”
在下例中,你可以用同层相邻组合选择器+
选择header
元素后紧跟的p
元素:
header + p { font-size: 1.1em } /* 图片后面紧跟着的段落将被选中 */ img + p { font-style: bold; }复制代码
同层全体组合选择器“~”
你也可以用同层全体组合选择器~
,选择所有跟在article
后的同层article
元素,不管它们之间隔了多少其他元素:
article ~ article { border-top: 1px dashed #ccc }复制代码
综合实例
article { ~ article { border-top: 1px dashed #ccc } > section { background: #eee } dl > { dt { color: #333 } dd { color: #555 } } nav + & { margin-top: 0 } }复制代码
sass
会如你所愿地将这些嵌套规则一一解开组合在一起:
article ~ article { border-top: 1px dashed #ccc } article > footer { background: #eee } article dl > dt { color: #333 } article dl > dd { color: #555 } nav + article { margin-top: 0 }复制代码
[4],嵌套属性
在sass
中,除了CSS选择器,属性也可以进行嵌套。
嵌套属性的规则是这样的:把属性名从中划线-的地方断开,在根属性后边添加一个冒号:,紧跟一个{ }
块,把子属性部分写在这个{ }
块中。就像css
选择器嵌套一样,sass
会把你的子属性一一解开,把根属性和子属性部分通过中划线-连接起来,最后生成的效果与你手动一遍遍写的css
样式一样:
nav { border: { // 与嵌套选择器不同点 style: solid; width: 1px; color: #ccc; } } 编译后 nav { border-style: solid; border-width: 1px; border-color: #ccc; }复制代码
对于属性的缩写形式,你甚至可以像下边这样来嵌套,指明例外规则:
nav { border: 1px solid #ccc { left: 0px; right: 0px; } }复制代码
这比下边这种同等样式的写法要好:
nav { border: 1px solid #ccc; border-left: 0px; border-right: 0px; }复制代码
属性和选择器嵌套是非常伟大的特性,因为它们不仅大大减少了你的编写量,而且通过视觉上的缩进使你编写的样式结构更加清晰,更易于阅读和开发。
5,其他常用语法
[1]注释
Sass 支持标准的 CSS 多行注释
/* */
,以及单行注释//
,前者会被完整输出到编译后的 CSS 文件中,而后者则不会。将
!
作为多行注释的第一个字符表示在压缩输出模式下保留这条注释并输出到 CSS 文件中,通常用于添加版权信息。(一般用)插值语句 (interpolation) 也可写进多行注释中输出变量值
例如:
/* hello world! */ // compile scss files to css // it's ready to do it. $pink: #f3e1e1; html{ background-color: $pink; } $author: 'gdream@126.com'; /*! Author: #{$author}. */复制代码
开发模式编译后:
/* hello world! */ html{ background-color: #f3e1e1; } /*! Author: 'gdream@126.com'. */复制代码
min模式输出模式编译后:
html{ background-color: #f3e1e1; } /*! Author: 'gdream@126.com'. */复制代码
[2],插值语法(重点)
通过 #{}
插值语句可以在选择器、属性名和属性值中使用变量。类似于js里的${}
但大多数情况下,这样使用属性值可能还不如直接使用变量方便,但是使用 #{}
可以避免 Sass 运行运算表达式,直接编译 CSS。
$n:front; #app .#{$n} { color:red; }复制代码
#app .front { color: red; }复制代码
$name: foo; $attr: border; p.#{$name} { #{$attr}-color: $name; } // 编译后: p.foo { border-color: foo; }复制代码
[3].!default
可以在变量的结尾添加 !default
给一个未通过 !default
声明赋值的变量赋值,此时,如果变量已经被赋值,不会再被重新赋值,但是如果变量还没有被赋值,则会被赋予新的值。
$content: "First content"; $content: "Second content?" !default; $new_content: "First time reference" !default; #main { content: $content; new-content: $new_content; } // 编译为: #main { content: "First content"; new-content: "First time reference"; }复制代码
注意:变量是 null 空值时将视为未被 !default
赋值。
[4].!global
将局部变量提升为全局变量(作用域)
6,@-Rules与指令(重点)
Sass 支持所有的 CSS3 @-Rules,以及 Sass 特有的 “指令”(directives)
[1]@import
css
有一个特别不常用的特性,即@import
规则,它允许在一个css
文件中导入其他css
文件。然而,后果是只有执行到@import
时,浏览器才会去下载其他css
文件,这导致页面加载起来特别慢。sass
也有一个@import
规则,但不同的是,sass
的@import
规则在生成css
文件时就把相关文件导入进来。这意味着所有相关的样式被归纳到了同一个css
文件中,而无需发起额外的下载请求。另外,所有在被导入文件中定义的变量和混合器均可在导入文件中使用。使用
sass
的@import
规则并不需要指明被导入文件的全名。你可以省略.sass
或.scss
文件后缀(见下图)。
例如:@import
"sidebar";这条命令将把sidebar.scss
文件中所有样式添加到当前样式表中。
导入格式要求
以下常见的不符合的
文件拓展名是
.css
;文件名以
http://
开头;文件名是
url()
;@import
包含 media queries
@import "foo.scss"; @import "foo"; // 以上两种方式均可 // 以下方式均不可行 @import "foo.css"; @import "foo" screen; @import "http://foo.com/bar"; @import url(foo);复制代码
Sass 允许同时导入多个文件,例如同时导入 rounded-corners 与 text-shadow 两个文件:
@import "rounded-corners", "text-shadow";复制代码
导入文件也可以使用 #{ }
插值语句,但不是通过变量动态导入 Sass 文件,只能作用于 CSS 的 url()
导入方式:
$family: unquote("Droid+Sans"); @import url("http://fonts.googleapis.com/css?family=#{$family}"); // 编译为: @import url("http://fonts.googleapis.com/css?family=Droid+Sans");复制代码
使用SASS部分文件
如果你有一个 SCSS 或 Sass 文件需要引入, 但是你又不希望它被编译为一个 CSS 文件, 这时,你就可以在文件名前面加一个下划线,就能避免被编译。 这将告诉 Sass 不要把它编译成 CSS 文件。 然后,你就可以像往常一样引入这个文件了,而且还可以省略掉文件名前面的下划线。
例如,将文件命名为 _colors.scss
,便不会编译 _colours.css
文件。
@import "colors";复制代码
上面的例子,导入的其实是 _colors.scss
文件
注意,不可以同时存在添加下划线与未添加下划线的同名文件,添加下划线的文件将会被忽略。
嵌套 @import
除此之外,还支持嵌套 @import,但是不可以在混合指令 (mixin) 或控制指令 (control directives) 中嵌套 @import
。
大多数情况下,一般在文件的最外层(不在嵌套规则内)使用 @import
,其实,也可以将 @import
嵌套进 CSS 样式或者 @media
中,与平时的用法效果相同,只是这样导入的样式只能出现在嵌套的层中。
假设 example.scss 文件包含以下样式:
.example { color: red; }复制代码
然后导入到 #main
样式内
#main { @import "example"; }复制代码
将会被编译为
#main .example { color: red; }复制代码
[2].@media(不常用)
Sass 中 @media
指令与 CSS 中用法一样,只是增加了一点额外的功能:允许其在 CSS 规则中嵌套。如果 @media
嵌套在 CSS 规则内,编译时,@media
将被编译到文件的最外层,包含嵌套的父选择器。这个功能让 @media
用起来更方便,不需要重复使用选择器,也不会打乱 CSS 的书写流程。
.sidebar { width: 300px; @media screen and (orientation: landscape) { width: 500px; } } // 编译为 .sidebar { width: 300px; @media screen and (orientation: landscape) { width: 500px; } }复制代码
@media
的 queries 允许互相嵌套使用,编译时,Sass 自动添加 and
@media screen { .sidebar { @media (orientation: landscape) { width: 500px; } } } // 编译为: @media screen and (orientation: landscape) { .sidebar { width: 500px; } }复制代码
@media
甚至可以使用 SassScript(比如变量,函数,以及运算符)代替条件的名称或者值
$media: screen; $feature: -webkit-min-device-pixel-ratio; $value: 1.5; @media #{$media} and ($feature: $value) { .sidebar { width: 500px; } } // 编译为: @media screen and (-webkit-min-device-pixel-ratio: 1.5) { .sidebar { width: 500px; } }复制代码
[3].@extend
@extend
即继承
。在设计网页的时候常常遇到这种情况:一个元素使用的样式与另一个元素完全相同,但又添加了额外的样式。
通常会在 HTML 中给元素定义两个 class,一个通用样式,一个特殊样式。假设现在要设计一个普通错误样式与一个严重错误样式,一般会这样写:
<div class="error seriousError"> Oh no! You've been hacked! </div>复制代码
a. 基本继承
.error { border: 1px #f00; background-color: #fdd; } .seriousError { @extend .error; border-width: 3px; } // 上面代码的意思是将 .error 下的所有样式继承给 .seriousError,border-width: 3px; 是单独给 .seriousError 设定特殊样式,这样,使用 .seriousError 的地方可以不再使用 .error。复制代码
@extend
的作用是将重复使用的样式 (.error
) 延伸 (extend) 给需要包含这个样式的特殊样式(.seriousError
)
其他使用到 .error
的样式也会同样继承给 .seriousError
,例如,另一个样式 .error.intrusion
使用了 hacked.png
做背景,<div class="seriousError intrusion">
也同样会使用 hacked.png
背景。
.error.intrusion { background-image: url("/image/hacked.png"); }复制代码
注意理解以下情况:
.error { border: 1px #f00; background-color: #fdd; } .error.intrusion { background-image: url("/image/hacked.png"); } .seriousError { @extend .error; border-width: 3px; } // .error, .seriousError { border: 1px #f00; background-color: #fdd; } .error.intrusion, .seriousError.intrusion { background-image: url("/image/hacked.png"); } .seriousError { border-width: 3px; }复制代码
当合并选择器时,@extend
会很聪明地避免无谓的重复,.seriousError.seriousError
将编译为 .seriousError
,不能匹配任何元素的选择器也会删除。
b. 继承复杂的选择器
Class 选择器并不是唯一可以被延伸 (extend) 的,Sass 允许延伸任何定义给单个元素的选择器,比如 .special.cool
,a:hover
或者 a.user[href^="http://"]
等
c. 多重继承
同一个选择器可以延伸继承给多个选择器,它所包含的属性将继承给所有被延伸的选择器
d. 多级继承
当一个选择器延伸给第二个后,可以继续将第二个选择器延伸给第三个
e.选择器列(不推荐使用)
暂时不可以将选择器列 (Selector Sequences),比如 .foo .bar
或 .foo + .bar
,延伸给其他元素,但是,却可以将其他元素延伸给选择器列。
尽量不使用合并选择器列
,因为如果凭个人推理的话,会出现排列组合的情况,所以SASS编译器只会保留有用的组合形式,但依旧会存在排列组合的情况,有可能会留下隐患。
当两个列合并时,如果没有包含相同的选择器,将生成两个新选择器:第一列出现在第二列之前,或者第二列出现在第一列之前
#admin .tabbar a { font-weight: bold; } #demo .overview .fakelink { @extend a; } // 编译为: #admin .tabbar a, #admin .tabbar #demo .overview .fakelink, #demo .overview #admin .tabbar .fakelink { font-weight: bold; }复制代码
如果两个列包含了相同的选择器,相同部分将会合并在一起,其他部分交替输出
#admin .tabbar a { font-weight: bold; } #admin .overview .fakelink { @extend a; } // 编译为 #admin .tabbar a, #admin .tabbar .overview .fakelink, #admin .overview .tabbar .fakelink { font-weight: bold; }复制代码
f. 在指令中延伸
在指令中使用 @extend
时(比如在 @media
中)有一些限制:Sass 不可以将 @media
层外的 CSS 规则延伸给指令层内的 CSS.
g. %placeholder
为选择器占位符,配合@extend-Only选择器
使用。
效果:只定义了样式,但不会对原有选择器匹配的元素生效
// example1: %img { color: red; } .path{ @extend %img; } // 编译后: .path { color: red; }复制代码
// example2: #context a%extreme { color: blue; font-weight: bold; font-size: 2em; } // 编译后: .notice { @extend %extreme; } // 注:必须是"."和"#"选择器复制代码
[4],不常见指令
遇到在学系列
a,@at-root
The @at-root directive causes one or more rules to be emitted at the root of the document, rather than being nested beneath their parent selectors. It can either be used with a single inline selector
译文:@at root指令使一个或多个规则在文档的根发出,而不是嵌套在其父选择器下。它可以与单个内联选择器一起使用
且@at-root 使多个规则跳出嵌套
@at-root默认情况下并不能使规则或者选择器跳出指令,通过使用without和with可以解决该问题
了解即可
b.@debug
用于调试,按标准错误输出流输出
$size: 9px; .file{ @debug $size; }复制代码
c,@warn
用于警告,按标准错误输出流输出
d.@error
用于报错,按标准错误输出流输出
序列 | @-rules | 作用 |
---|---|---|
1 | @import | 导入sass或scss文件 |
2 | @media | 用于将样式规则设置为不同的媒体类型 |
3 | @extend | 以继承的方式共享选择器 |
4 | @at-root | 转到根节点 |
5 | @debug | 用于调试,按标准错误输出流输出 |
6 | @warn | 用于警告,按标准错误输出流输出 |
7 | @error | 用于报错,按标准错误输出流输出 |
7,控制指令 (Control Directives)
[1].if()
三元运算符
表达式:if(expression, value1, value2)
p { color: if(1 + 1 == 2, green, yellow); } // compile:(编译后) p{ color: green;}复制代码
[2].@if
条件语句
当 @if
的表达式返回值不是 false
或者 null
时,条件成立,输出 {}
内的代码
@if
声明后面可以跟多个 @else if
声明,或者一个 @else
声明。如果 @if
声明失败,Sass 将逐条执行 @else if
声明,如果全部失败,最后执行 @else
声明
单@if
p { @if 1 + 1 == 2 { color: red; } } // compile: p { color: red; }复制代码
@if - @else
p { @if 1 + 1 != 2 { color: red; } @else { color: blue; } } // compile: p { color: blue; }复制代码
@if - @else if - @else
$age: 19; p { @if $age == 18 { color: red; } @else if $age == 19 { color: blue; } @else { color: green; } } // compile: p { color: blue; }复制代码
[3].@for
两种循环语句
@for $var from <start> through <end>
@for $var from <start> to <end>
through 和 to 的相同点与不同点:
相同点:两者均包含的值
不同点:through包含的值,但to不包含的值
@for $i from 1 through 3 { .item-#{$i} { width: 2em * $i; } } // compile: .item-1 { width: 2em; } .item-2 { width: 4em; } .item-3 { width: 6em; }复制代码
[4].@while
循环语句
表达式:@while expression
@while
指令重复输出格式直到表达式返回结果为 false
。这样可以实现比 @for
更复杂的循环,只是很少会用到
$i: 6; @while $i > 0 { .item-#{$i} { width: 2em * $i; } $i: $i - 2; } // compile: .item-6 { width: 12em; } .item-4 { width: 8em; } .item-2 { width: 4em; }复制代码
[5].@each
循环语句
表达式:$var in $vars
$var
可以是任何变量名
$vars
只能是Lists
或者Maps
一维列表
@each $animal in puma, sea-slug, egret, salamander { .#{$animal}-icon { background-image: url('/images/#{$animal}.png'); } } // compile: .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'); }复制代码
二维列表
@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; } } // compile: .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; }复制代码
maps
@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) { #{$header} { font-size: $size; } } // compile: h1 { font-size: 2em; } h2 { font-size: 1.5em; } h3 { font-size: 1.2em; }复制代码
8、混合器@mixin(重点)
如果你的整个网站中有几处小小的样式类似(例如一致的颜色和字体),那么使用变量来统一处理这种情况是非常不错的选择。但是当你的样式变得越来越复杂,你需要大段大段的重用样式的代码,独立的变量就没办法应付这种情况了。你可以通过sass
的混合器实现大段样式的重用。
[^] 注意:这不是函数!没有返回值!!
[1].定义混合器
混合指令的用法是在 @mixin
后添加名称与样式,以及需要的参数(可选)。
// 格式: @mixin name { // 样式.... }复制代码
// example: @mixin large-text { font: { family: Arial; size: 20px; weight: bold; } color: #ff0000; }复制代码
[2].引用混合样式@include
使用 @include
指令引用混合样式,格式是在其后添加混合名称,以及需要的参数(可选)。
// 格式: @include name; // 注:无参数或参数都有默认值时,带不带括号都可以复制代码
// example: p { @include large-text; } // compile: p { font-family: Arial; font-size: 20px; font-weight: bold; color: #ff0000; }复制代码
[3].参数
格式:按照变量的格式,通过逗号分隔,将参数写进Mixin名称后的圆括号里
支持默认值;支持多参数;支持不定参数;支持位置传参和关键词传参
a. 位置传参
@mixin mp($width) { margin: $width; } body { @include mp(300px); }复制代码
b.关键词传参
@mixin mp($width) { margin: $width; } body { @include mp($width: 300px); }复制代码
c.参数默认值
@mixin mp($width: 500px) { margin: $width; } body { @include mp($width: 300px); // or @include mp(300px); }复制代码
d.不定参数
官方:Variable Arguments
译文:参数变量
有时,不能确定混合指令需要使用多少个参数。这时,可以使用参数变量
…
声明(写在参数的最后方)告诉 Sass 将这些参数视为值列表处理
@mixin mar($value...) { margin: $value; }复制代码
[4].向混合样式中导入内容
在引用混合样式的时候,可以先将一段代码导入到混合指令中,然后再输出混合样式,额外导入的部分将出现在 @content
标志的地方
可以看作参数的升级版
@mixin example { html { @content; } } @include example{ background-color: red; .logo { width: 600px; } } // compile: html { background-color: red; } html .logo { width: 600px; }复制代码
9,函数指令
[1].内置函数(查阅用)
a. 字符串函数
索引第一个为1,最后一个为-1;切片两边均为闭区间
函数名和参数类型 | 函数作用 |
---|---|
quote($string) | 添加引号 |
unquote($string) | 除去引号 |
to-lower-case($string) | 变为小写 |
to-upper-case($string) | 变为大写 |
str-length($string) | 返回$string的长度(汉字算一个) |
str-index(string,string,string,substring) | 返回substring在substring在substring在string的位置 |
str-insert(string,string,string,insert, $index) | 在string的string的string的index处插入$insert |
str-slice(string,string,string,start-at, $end-at) | 截取string的string的string的start-at和$end-at之间的字符串 |
b. 数字函数
函数名和参数类型 | 函数作用 |
---|---|
percentage($number) | 转换为百分比形式 |
round($number) | 四舍五入为整数 |
ceil($number) | 数值向上取整 |
floor($number) | 数值向下取整 |
abs($number) | 获取绝对值 |
min($number...) | 获取最小值 |
max($number...) | 获取最大值 |
random($number?:number) | 不传入值:获得0-1的随机数;传入正整数n:获得0-n的随机整数(左开右闭) |
c. 数组函数
函数名和参数类型 | 函数作用 |
---|---|
length($list) | 获取数组长度 |
nth($list, n) | 获取指定下标的元素 |
set-nth(list,list,list,n, $value) | 向list的list的list的n处插入$value |
join(list1,list1,list1,list2, $separator) | 拼接list1和list2;list1和list2;list1和list2;separator为新list的分隔符,默认为auto,可选择comma、space |
append(list,list,list,val, $separator) | 向list的末尾添加list的末尾添加list的末尾添加val;$separator为新list的分隔符,默认为auto,可选择comma、space |
index(list,list,list,value) | 返回value值在value值在value值在list中的索引值 |
zip($lists…) | 将几个列表结合成一个多维的列表;要求每个的列表个数值必须是相同的 |
d. 映射函数
函数名和参数类型 | 函数作用 |
---|---|
map-get(map,map,map,key) | 获取map中map中map中key对应的$value |
map-merge(map1,map1,map1,map2) | 合并map1和map1和map1和map2,返回一个新$map |
map-remove(map,map,map,key) | 从map中删除map中删除map中删除key,返回一个新$map |
map-keys($map) | 返回map所有的map所有的map所有的key |
map-values($map) | 返回map所有的map所有的map所有的value |
map-has-key(map,map,map,key) | 判断map中是否存在map中是否存在map中是否存在key,返回对应的布尔值 |
keywords($args) | 返回一个函数的参数,并可以动态修改其值 |
e. 颜色函数
RGB函数
函数名和参数类型 函数作用 rgb(red,red,red,green, $blue) 返回一个16进制颜色值 rgba(red,red,red,green,blue,blue,blue,alpha) 返回一个rgba;red,red,red,green和$blue可被当作一个整体以颜色单词、hsl、rgb或16进制形式传入 red($color) 从$color中获取其中红色值 green($color) 从$color中获取其中绿色值 blue($color) 从$color中获取其中蓝色值 mix(color1,color1,color1,color2,$weight?) 按照weight比例,将weight比例,将weight比例,将color1和$color2混合为一个新颜色 HSL函数
函数名和参数类型 函数作用 hsl(hue,hue,hue,saturation,$lightness) 通过色相(hue)、饱和度(saturation)和亮度(lightness)的值创建一个颜色 hsla(hue,hue,hue,saturation,lightness,lightness,lightness,alpha) 通过色相(hue)、饱和度(saturation)、亮度(lightness)和透明(alpha)的值创建一个颜色 saturation($color) 从一个颜色中获取饱和度(saturation)值 lightness($color) 从一个颜色中获取亮度(lightness)值 adjust-hue(color,color,color,degrees) 通过改变一个颜色的色相值,创建一个新的颜色 lighten(color,color,color,amount) 通过改变颜色的亮度值,让颜色变亮,创建一个新的颜色 darken(color,color,color,amount) 通过改变颜色的亮度值,让颜色变暗,创建一个新的颜色 hue($color) 从一个颜色中获取亮度色相(hue)值 Opacity函数
alpha(color)/opacity(color)/opacity(color)/opacity(color) 获取颜色透明度值 rgba(color,color,color,alpha) 改变颜色的透明度 opacify(color,color,color,amount) / fade-in(color,color,color,amount) 使颜色更不透明 transparentize(color,color,color,amount) / fade-out(color,color,color,amount) 使颜色更加透明
f. Introspection函数
函数名和参数类型 | 函数作用 |
---|---|
type-of($value) | 返回$value的类型 |
unit($number) | 返回$number的单位 |
unitless($number) | 判断$number是否带单位,返回对应的布尔值 |
comparable(number1,number1,number1,number2) | 判断number1和number1和number1和number2是否可以做加、减和合并,返回对应的布尔值 |
[2].自定义函数(重点)
Sass 支持自定义函数,并能在任何属性值或 Sass script 中使用:
基本格式:
@function fn-name($params...) { @return $params; } //可传参,可return复制代码
$grid-width: 40px; $gutter-width: 10px; @function grid-width($n) { @return $n * $grid-width + ($n - 1) * $gutter-width; } #sidebar { width: grid-width(5); }复制代码
编译为
#sidebar { width: 240px; }复制代码
与 mixin 相同,也可以传递若干个全局变量给函数作为参数。一个函数可以含有多条语句,需要调用 @return
输出结果。
自定义的函数也可以使用关键词参数,上面的例子还可以这样写:
#sidebar { width: grid-width($n: 5); }复制代码
建议在自定义函数前添加前缀避免命名冲突,其他人阅读代码时也会知道这不是 Sass 或者 CSS 的自带功能。
自定义函数与 mixin 相同,都支持 variable arguments
补充:
@extend、@Mixin和@function的选择
根据csswizardry.com/2016/02/mix…
minxins在网络传输中比
@extend拥有更好的性能.尽管有些文件未压缩时更大,但使用
gzip`压缩后,依然可以保证我们拥有更好的性能。
所以@extend我们就尽量不要使用了,而@Mixin和@function的差别在定义和使用上
定义方式不同:
@function
需要调用@return
输出结果。而 @mixin则不需要。使用方式不同:
@mixin
使用@include
引用,而@function
使用小括号执行函数。
作者:哈哈与黑洞大笑
链接:https://juejin.cn/post/7023376064357335071