Sass is the most mature,stable,and powerful profrssional grade CSS extension language in the world
Sass 是这个世界上最成熟、稳定和强大的专业级CSS扩展语言!
安装
Sass是Ruby语言写的,虽然两者的语法没有关系,但是必须先安装Ruby,然后再安装Sass
- 安装Ruby 直接在官网下载rubyinstall的安装包并下载devkit的开发拓展包
- 安装Sass
Sass使用变量
sass引入了变量, 可以把反复使用的css属性值定义成变量,然后通过变量名来引用它们,而无需重复书写这一属性值
sass使用$符号来标识变量(更好人、更具美感、在CSS中并无他用)
变量声明
//任何可以用作css属性值的赋值都可以用作sass的变量值,甚至是以空格分割的多个属性值
$highLight-color: #F90;
变量引用
与css属性不同, 变量可以在css规则块定义之外存在, 当变量定义在css规则块内, 那么该变量只能在规则块内使用。如果它们出现在任何形式的{…}块中(如@media或者@font-face块)
/*$nav-color定义在了规则块外面,所以这个样式表中都可以像nav规则块那样引用它。$width这个变量定义在了nav的{}规则块内,所以它只能在nav规则块内使用*/
$nav-color: #f590;
nav{ $width:100px; width:$width; color:#nav-color; }
变量名
sass的变量名中的属性名和选择器名称相同, 包括中划线和下划线。
sass并不想强迫任何人一定使用中划线或下划线, 所以这两种用法互相兼容。用中划线声明的变量可以使用下划线的方式引用。
嵌套CSS规则
css中重复写选择器是非常恼人的。如果要写一大串指向页面中同一块的样式时, 往往需要一遍又一遍地写同一个ID:
#content article h1 { color:#333 }
#content article p { margin-bottom:1.4em }
#content aside {background-color:#eee}
像这种情况, sass可以让人只写一遍, 且使样式可读性更高。在sass中, 可以像俄罗斯套娃那样在规则块中嵌套规则块。sass在输出时会把嵌套规则处理好。
#content {
article {
h1 { color:#333 }
p { margin-bottom:1.4em }
}
aside { background:#EEE }
}
一个给定的规则块, 既可以像普通css那样包含属性, 又可以嵌套其他规则块。当同时要为一个容器元素及其子元素编写特定样式时, 就非常有用
#content {
background-color:#f5f5f5;
aside { background-color:#eee; }
}
/*容器元素的样式规则会被单独抽离出来, 而嵌套元素的样式规则会像容器元素没有包含任何属性时那样被抽离出来*/
/*
#content { background-color:#f5f5f5; }
#content aside { background-color:#eee }
*/
父选择器的标识符&
如果想要在嵌套的选择器里面立刻应用一个类似于:hover的伪类, 这种简单的嵌套就不行。为了解决这种和别的特殊情况, sass提供了一个特殊结构&
/*为链接元素写:hover这种伪类时,并不希望以后代选择器的方式连接*/
/*错误*/
article a {
color:blue;
:hover {color:red}
}
/*这意味着 color:red 这条规则将被应用到选择器 article a :hover */
/*article元素内链接的所有子元素在被hover时都会变成红色*/
/*这是不正确的!*/
解决之道就是使用一个特殊的sass选择器, 即父选择器。在使用嵌套规则时, 父选择器能对于嵌套规则如何解开提供更好的控制。它就是一个简单的&符号, 且可以放在任何一个选择器可出现的地方。
article a {
color: blue;
&:hover { color:red }
}
/*编译后*/
/*
article a { color:blue }
article a:hover{ color:red }
*/
父选择器还有一种用法, 就是可以在父选择器之前添加选择器。举例来说, 当用户在使用IE浏览器时, 可以通过javascript在标签上添加一个ie的类名
#content aside {
color : red;
body.ie & { color : green }
}
/*编译后*/
/*
#content aside { color:red }
body.ie #content aside { color:green }
*/
即使是带有父选择器的情况, 当sass遇到群组选择器(多个逗号分隔开的选择器)也能完美地处理这种嵌套
群组选择器的嵌套
.container {
h1, h2, h3 { margin-bottom: .8em }
}
/*编译后*/
/*
.container h1, .container h2, .container h3 {
margin-bottom: .8em
}
*/
- 优点: 大大减少了工作量
- 缺点: 虽然sass的样式表看起来很小, 但实际生成的css却可能非常大, 这会降低网站的速度
嵌套属性
sass中, 除了css选择器, 属性也可以进行嵌套。把属性名从中划线-的地方断开, 在根属性后面添加一个冒号; 紧跟一个{}块, 把子属性部分写在这个{}块中
nav {
border:{
style : solid;
width : 1px;
color : #ccc;
}
}
导入Sass文件
css有一个特别不常用的特性, 即@import规则, 它允许在一个css文件中导入其他css文件。然而,
后果是只有执行到@import时, 浏览器才会去下载其他css文件, 这导致页面加载起来特别慢 sass也有一个@import规则,
但不同的是, sass的@import规则, sass的@import规则在生成文件时就把相关文件导入进来。这意味着所有相关的样式被归纳到了同一个css文件中, 而无需发起额外的下载请求。另外, 所有在被导入文件中定义的变量和混合器均可在导入文件在使用
嵌套导入
跟原生的css不停, sass允许@import命令写在css规则内。这种导入方式下, 生成对应的css文件时, 局部文件会被直接插入到css规则内导入它的地方。
/* _blue-theme.scss*/
aside{
background:blue;
color:white
}
.blue-theme { @import "blue-theme" }
/*编译后*/
/*.blue-theme aside{
background:blue;
color:white;
}
*/
被导入的局部文件中定义的所有变量和混合器, 也会在这个规则范围内生效。这些变量和混合器不会全局有效, 这样我们就可以通过嵌套导入只对站点中某一特点区域运用某种颜色主体或其他通过变量配置的样式。
原生的css导入
由于sass兼容原生的css,所以它也支持原生的css@import。尽管通常在sass中使用@import时, sass会尝试找到对应的sass文件并导入进来, 但在下列三种情况下会生成原生的CSS@import, 尽管这会造成浏览器解析css时的额外下载:
- 被导入文件的名字以.css结尾;
- 被导入文件的名字是一个URL地址
- 被导入文件的名字是CSS的url值
默认变量值
一般情况下, 反复声明一个变量, 后面部分的声明会覆盖前面的值, 但这可能不是想要的结果。假如你写了一个可被他人@import导入的sass库文件, 你可能希望导入者可以定制修改sass库文件中的某些值。使用sass的!default标签可以实现这个目的。它很像css属性中!important标签的对立面,不同的是!default用于变量,含义是:如果这个变量被声明赋值了,那就用它声明的值,否则就用这个默认值
静默注释
sass提供了一种静默注释语法, 其内容不会出现在生成的css文件中, 它们以//开头, 注释内容直到行末
body{
color:#333; //这种注释内容不会出现在生成的css文件中
padding:0; /*这种注释内容会出现在生成的css文件中*/
margin:1 /*这种注释内容也不会出现在生成的css文件中*/ 0;
}
混合器
如果网站中有几处小小的样式类似, 那么使用变量来统一处理是不错的选择, 但是当样式变得越来越复杂, 需要大段大段地重用样式的代码, 就可以通过sass的混合器实现大段样式的重用
混合器使用@mixin标识符定义
在样式表中通过@include来使用这个混合器, 放在希望的任何地方。@include调用会把混合器中所有样式提取出来放在@include被调用的地方
/*添加浏览器的圆角边框*/
@mixin rounded-corners{
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
notice{
background-color: green;
border: 2px solid #00aa00;
@include rounded-corners;
}
- 大量的重用可能会导致生成的样式表过大, 导致加载缓慢
- 当样式本身就是一个逻辑单元, 或者是一组放在有意义的属性, 那就应该把这段样式构造成优良的混合器
给混合器传参
混合器不一定总得生成相同的样式。可以通过在@include混合器时给混合器传参, 来定制混合器生成的精确样式。当@include混合器时, 参数其实就是可以赋值给css属性值的变量, 这跟JavaScript的function很像
@mixin link-colors($normal,$hover,$visited){
color: $normal;
&:hover: { color:&hover }
&:visited { color:$visited }
}
a{
@include link-colors(blue, red, green)
}
sass允许通过语法 $name:value 的形式指定每个参数的值。 这种形式的传参, 参数顺序就不必再在乎了, 只需要保证没有漏掉参数即可
a {
@include link-colors{
$normal: blue,
$visited: green,
$hover: red
}
}
sass允许混合器声明时给参数默认值。参数默认值使用 $name: default-value 的声明形式, 默认值可以是任何有效的css属性值, 或者是其他参数的引用。
@mixin link-colors($normal:red,$hover:green,$visited:blue){
color: $normal,
&:hover { color:$hover }
&:visited { color:$visited }
}
sass 继承
使用sass的时候, 最后一个减少重复的主要特性就是选择器继承。基于Nicole Sullivan 面向对象的css的理念, 选择器继承是说一个选择器可以继承为另一个选择器定义的所有样式, 这个通过@entend语法实现
.error {
border: 1px red;
background-color: #fdd;
}
.seriousError{
@extend .error;
border-width: 3px;
}
要继承的不仅仅是一个类名, 也可以是一个id也可以是一个元素, 也可以是某个状态, 任何选择器都能继承
.hoverlink{
@entend a:hover
}
a:hover{
text-decoraion:underline;
}
/*
a:hover, .hoverlink{
text-decoration:underline;
}
*/
虽然能够继承的选择器数量很多, 但是也有很多选择器并不被支持继承的, 如包含选择器(.one .two)或者相邻兄弟选择器(.one+.two)目前还是不支持继承
继承在指令中是有作用域问题的, 继承是无法使在指令如(@media)之外的选择器继承的, 钥匙继承就只能写在指令中
sass函数
sass内置了一系列函数, 主要包含: 字符串函数、数字函数、列表函数、Introspection函数、三元函数以及颜色函数等。
字符串函数
- unquote($string): 删除字符串中的引号
- quote($string): 给字符串添加引号
/* unquote()函数主要是用来删除一个字符串中的引号,如果这个字符串没有带引号,将返回原始的字符串 */
/*scss*/
.test1{
content: unquote('Hello Sass')!
}
.test2{
content: unquote("'Hello Sass!")
}
.test3{
content: unquote("I'm Web Designer")
}
.test4{
content: unquote("'Hello Sass!'")
}
.test5{
content: unquote('"Hello Sass!"')
}
.test6{
content: unquote(Hello Sass)
}
/*css*/
.test1{
content: Hello Sass!
}
.test2{
content: 'Hello Sass!
}
.test3{
content: I'm Web Designer
}
.test4{
content: 'Hello Sass!'
}
.test5{
content: "Hello Sass!"
}
.test6{
content: Hello Sass!
}
/*quote()函数刚好与unquote()函数功能相反,主要用来给字符串添加引号。如果字符串自身带有引号会统一换成双引号*/
数字函数
sass中的数字函数主要针对数字方面提供一系列的函数功能
- percentage($value): 将一个不带单位的数转换成百分比值
- round($value): 将数组四舍五入, 转换成一个最接近的整数
- ceil($value): 将大于自己的小数转换成下一位整数
- floor($value): 将一个数去除他的小数部分
- abs($value): 返回一个数的绝对值
- min($numbers…): 返回一个数值之间的最小值
- max($numbers…): 好啊出几个数值之间的最大值
列表函数
- length($list): 返回一个列表的长度值
- nth($list, $n): 返回一个列表中指定的某个标签页
- join( $ list1, $ list2, [$separator]): 将两个列给连接在一起, 变成一个列表
- append($ list1, $ val, [$separator]): 将某个值放在列表的最后
- zip($lists…): 将几个列表结合成一个多维的列表
- index($index, $value): 返回一个值在列表中的位置值
/*length()函数中的列表参数之间使用空格隔开, 不能使用逗号, 否则函数将会报错 */
length(10px 20px (border 1px solid) 2em) //4
/*nth用来指定列表中某个位置的值,不过与其他语言不同的是,1是指列表中的第一个值,2是指列表中的第二个值*/
nth(10px 20px 30px, 1) //10px
/*join()将两个列表合并成一个列表,如果直接连接两个以上的列表会报错, $separator这个参数主要给列表函数链接列表使用的分隔符号,默认值为auto,除了auto以外,还有commma和space两个值,其中comma值指定列表中的列表项值之间使用逗号(,)分隔,space值指定列表中的列表项值之间使用空格( )分隔*/
join(10px 20px, 30px 40px) //(10px 20px 30px 40px)
/*入股偶列表中的第一个列表中的每个值之间使用的是逗号,那么join()的函数合并的列表中每个列表项之间使用逗号分隔*/
join((blue,red,#eff),(green orange)) //(#0000ff,#ff00000,#eeffff,#008000,#ffa500)
/*当第一个列表中只有一个列表项,那么分隔符根据第二个列表项中的*/
join(blue,(green orange)) //(blue green orange)
/*指明合并的$separator参数*/
join(blue,red,comma) //(#0000ff,#ff0000)
/*append将某个值插入列表中最末尾,$separator参数规则与上类似*/
append(10px 20px,30px) //(10px 20px 30px)
/*zip()函数将多个列表值转成一个多维的列表,每个单一的列表个数值必须是相同的*/
zip(1px 2px 3px, solid dashed dotted, green blue red) //((1px solid green),(2px dashed),(3px dotted red))
/*index()函数类似于索引一样,在sass中,第一个值就是1,第二值就是2*/
index(1px solid red, 1px) //1
/*在index()函数中,如果指定的值不再列表中,那么返回的值将是false*/
index(1px solid red, dotted) //false
三元函数
Introspection 函数包括了几个判断型函数:
- type-of($value): 返回一个值的类型
- unit($number): 返回一个值的单位
- unitless($number): 判断一个值是否带有单位
- comparable($number-1, $number-2): 判断两个值是否可以做加、减和合并这几个函数
- Miscellaneous函数: 三元条件函数
type-of(100) //'number'
typeof('dsds') //'string'
typeof('#fff') //'color'
typeof(true) //'bool'
/*unit()碰到复杂运算时,能根据运算得到一个多单位组合的值,不过只允许加减乘除*/
unit(20%) //%
unit(10px * 3em) // px * 3em
/*unitless不带单位返回的值为true,带单位返回的值为false*/
unitless(100) //true
unitless(20px) //false
/*comparable()可以运算返回的值为true,不可以返回false*/
comparable(2px,1em) //false
comparable(2px,1cm) //true
/*当条件成立返回一种值,当条件不成立返回另一种值*/
if($condition,$if-true,$if-false)
if(true, 1px, 2px) //1px
if(false, 1px, 2px) //2px
颜色函数
- rgb($red, $green, $blue): 根据红、绿、蓝三个值创建一个颜色
- rgba($red, $green, $blue): 根据红、绿、蓝和透明值创建一个颜色
- red($color): 从一个颜色中获取其中红色值
- green($color): 从一个颜色中获取其中绿色值
- blue($color): 从一个颜色中获取其中蓝色值
- mix($color-1, c o l o r − 2 , [ color-2, [ color−2,[weight]): 把两种颜色混合在一起
自定义函数
自定义函数式用户根据自己的特殊需求编写的Sass函数
//去掉一个值的单位, 如12px => 12
@function stripUnits($number){
@return $number / ($number * 0 + 1 )
}
sass高级语法
条件语句
/*@if可以用来判断*/
p{
@if 1+1 == 2 { border: 1px solid }
@if 5 < 3 { border:2px dotted }
}
/*配套的还有@else*/
@if lightness($color) > 30%{
background-color: #000
}@else{
background-color: #eee
}
循环语句
@for $i form 1 to 10{
.border-#{$i}{
border:#{$i}px solid blue
}
}
$i:6;
@while $i > 0{
.item-#{$i} { width:2em * $i }
$i : $i-2
}