Sass 是对 CSS 的扩展,允许使用变量、嵌套规则、 mixins、导入等功能, 完全兼容 CSS 语法。
Sass 有两种语法:
- 第一种被称为 SCSS (Sassy CSS),是一个 CSS3 语法的扩充版本
- 第二种比较老的语法:缩排语法(或者就称为 “Sass”)
https://www.npmjs.com/package/sass
https://www.npmjs.com/package/node-sass
1 2 3 4 5 6 7 8 9 10
| var sass = require('node-sass') sass.render({ file: scss_filename, }, function(err, result) { })
var result = sass.renderSync({ data: scss_content });
|
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| var sass = require('node-sass'); sass.render({ file: '/path/to/myFile.scss', data: 'body{background:blue; a{color:black;}}', importer: function(url, prev, done) { someAsyncFunction(url, prev, function(result){ done({ file: result.path, contents: result.data }); }); var result = someSyncFunction(url, prev); return {file: result.path, contents: result.data}; }, includePaths: [ 'lib/', 'mod/' ], outputStyle: 'compressed' }, function(error, result) { if (error) { console.log(error.status); console.log(error.column); console.log(error.message); console.log(error.line); } else { console.log(result.css.toString()); console.log(result.stats); console.log(result.map.toString()); console.log(JSON.stringify(result.map)); } });
var result = sass.renderSync({ file: '/path/to/file.scss', data: 'body{background:blue; a{color:black;}}', outputStyle: 'compressed', outFile: '/to/my/output.css', sourceMap: true, importer: function(url, prev, done) { someAsyncFunction(url, prev, function(result){ done({ file: result.path, contents: result.data }); }); var result = someSyncFunction(url, prev); return {file: result.path, contents: result.data}; } })); console.log(result.css); console.log(result.map); console.log(result.stats);
|
变量
$
符号标识变量,包括中划线和下划线
- 变量可以在css规则块定义之外存在
- 当变量定义在css规则块内,那么该变量只能在此规则块内使用
支持 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)
1 2 3 4 5 6 7 8 9 10
| $nav-color: #F90; $highlight-color: #F90; $highlight-outline: 1px solid $highlight-color; nav { $width: 100px; width: $width; color: $nav-color; border: 1px solid $highlight-color; outline: $highlight-outline; }
|
编译后
1 2 3 4 5 6
| nav { width: 100px; color: #F90; border: 1px solid #F90; outline: 1px solid #F90; }
|
圆括号
1 2 3
| p { width: 1em + (2em * 3); }
|
=>
插值语句
#{}
1 2 3 4 5 6 7 8 9 10
| $name: foo; $attr: border; p.#{$name} { #{$attr}-color: blue; } p { $font-size: 12px; $line-height: 30px; font: #{$font-size}/#{$line-height}; }
|
1 2 3 4 5 6
| p.foo { border-color: blue; } p { font: 12px/30px; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| .sidebar { width: 300px; @media screen and (orientation: landscape) { width: 500px; } } @media screen { .sidebar { @media (orientation: landscape) { width: 500px; } } } $media: screen; $feature: -webkit-min-device-pixel-ratio; $value: 1.5; @media #{$media} and ($feature: $value) { .sidebar { width: 500px; } }
|
=>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| .sidebar { width: 300px; } @media screen and (orientation: landscape) { .sidebar { width: 500px; } } @media screen and (orientation: landscape) { .sidebar { width: 500px; } } @media screen and (-webkit-min-device-pixel-ratio: 1.5) { .sidebar { width: 500px; } }
|
嵌套
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #content { article { h1 { color: #333 } p { margin-bottom: 1.4em } a { color: blue; &:hover { color: red } } } aside { background-color: #EEE; body.ie & { color: green } } } .container { h1, h2, h3 {margin-bottom: .8em} } nav, aside { a {color: blue} } article { ~ article { border-top: 1px dashed #ccc } > section { background: #eee } dl > { dt { color: #333 } dd { color: #555 } } nav + & { margin-top: 0 } } nav { border: { style: solid; width: 1px; color: #ccc; } } nav { border: 1px solid #ccc { left: 0px; right: 0px; } }
|
编译后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #content article h1 { color: #333 } #content article p { margin-bottom: 1.4em } #content article a { color: blue } #content article a:hover { color: red } #content aside { background-color: #EEE } body.ie #content aside { color: green } .container h1, .container h2, .container h3 { margin-bottom: .8em } nav a, aside a {color: blue} 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 } nav { border-style: solid; border-width: 1px; border-color: #ccc; } nav { border: 1px solid #ccc; border-left: 0px; border-right: 0px; }
|
导入SASS文件
@import
如: @import "themes/night-sky";
默认变量值
!default
如果这个变量被声明赋值了,那就用它声明的值,否则就用这个默认值
1 2 3 4
| $fancybox-width: 400px !default; .fancybox { width: $fancybox-width; }
|
如果在导入sass局部文件之前声明了一个$fancybox-width变量,那么局部文件中对$fancybox-width赋值400px的操作就无效。
如果用户没有做这样的声明,则$fancybox-width将默认为400px
嵌套导入
如:
1 2 3 4 5
| aside { background: blue; color: white; }
|
导入到一个css规则内
1 2 3 4 5 6 7 8
| .blue-theme {@import "blue-theme"} // 生成的结果跟直接在.blue-theme选择器内写_blue-theme.scss文件的内容完全一样 .blue-theme { aside { background: blue; color: #fff; } }
|
原生的CSS导入
三种情况下会生成原生的CSS@import
- 被导入文件的名字以.css结尾;
- 被导入文件的名字是一个URL地址,由此可用谷歌字体API提供的相应服务;
- 被导入文件的名字是CSS的url()值。
静默注释
混合器
用 @mixin
标识符定义,通过 @include
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| @mixin rounded-corners { -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; } @mixin no-bullets { list-style: none; li { list-style-image: none; list-style-type: none; margin-left: 0px; } } @mixin link-colors($normal, $hover, $visited) { color: $normal; &:hover { color: $hover; } &:visited { color: $visited; } } .notice { background-color: green; border: 2px solid #00aa00; @include rounded-corners; } ul.plain { color: #444; @include no-bullets; } a { @include link-colors(blue, red, green); } a { @include link-colors( $normal: blue, $visited: green, $hover: red ); }
|
生成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| .notice { background-color: green; border: 2px solid #00aa00; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; } ul.plain { color: #444; list-style: none; } ul.plain li { list-style-image: none; list-style-type: none; margin-left: 0px; } a { color: blue; } a:hover { color: red; } a:visited { color: green; }
|
默认参数值
1 2 3 4 5 6
| @mixin link-colors($normal,$hover: $normal,$visited: $normal) { color: $normal; &:hover { color: $hover; } &:visited { color: $visited; } }
|
选择器继承
@extend
一个选择器可以继承为另一个选择器定义的所有样式
1 2 3 4 5 6 7 8
| .error { border: 1px solid red; background-color: #fdd; } .seriousError { @extend .error; border-width: 3px; }
|
.seriousError
不仅会继承 .error
自身的所有样式,任何跟 .error
有关的组合选择器样式也会被 .seriousError
以组合选择器的形式继承
1 2 3 4 5 6 7 8 9
| .error a{ color: red; font-weight: 100; }
h1.error { font-size: 1.2rem; }
|
@at-root
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| .parent { ... @at-root .child { ... } } .parent { ... @at-root { .child1 { ... } .child2 { ... } } .step-child { ... } } @media print { .page { width: 8in; @at-root (without: media) { color: red; } } }
|
=>
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| .parent { ... } .child { ... } .parent { ... } .child1 { ... } .child2 { ... } .parent .step-child { ... } @media print { .page { width: 8in; } } .page { color: red; }
|
@debug
=>
@warn、@error
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @mixin adjust-location($x, $y) { @if unitless($x) { @warn "Assuming #{$x} to be in pixels"; $x: 1px * $x; } @if unitless($y) { @warn "Assuming #{$y} to be in pixels"; $y: 1px * $y; } position: relative; left: $x; top: $y; } @mixin adjust-location($x, $y) { @if unitless($x) { @error "$x may not be unitless, was #{$x}."; } @if unitless($y) { @error "$y may not be unitless, was #{$y}."; } position: relative; left: $x; top: $y; }
|
占位符选择器
%foo
与常用的 id 与 class 选择器写法相似,只是 # 或 . 替换成了 %。必须通过 @extend 指令调用
单独使用时,不会被编译到 CSS 文件中
1 2 3 4 5 6 7 8 9
| #context a%extreme { color: blue; font-weight: bold; font-size: 2em; } .notice { @extend %extreme; }
|
=>
1 2 3 4 5
| #context a.notice { color: blue; font-weight: bold; font-size: 2em; }
|
控制指令
@if
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| p { @if 1 + 1 == 2 { border: 1px solid; } @if 5 < 3 { border: 2px dotted; } @if null { border: 3px double; } } $type: monster; p { @if $type == ocean { color: blue; } @else if $type == matador { color: red; } @else if $type == monster { color: green; } @else { color: black; } }
|
编译为
1 2 3 4 5 6
| p { border: 1px solid; } p { color: green; }
|
@for
1 2 3
| @for $i from 1 through 3 { .item-#{$i} { width: 2em * $i; } }
|
=>
1 2 3 4 5 6 7 8 9
| .item-1 { width: 2em; } .item-2 { width: 4em; } .item-3 { width: 6em; }
|
@each
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @each $animal in puma, sea-slug, egret, salamander { .#{$animal}-icon { background-image: url('/images/#{$animal}.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; } } @each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) { #{$header} { font-size: $size; } }
|
=>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| .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; } h1 { font-size: 2em; } h2 { font-size: 1.5em; } h3 { font-size: 1.2em; }
|
@while
1 2 3 4 5
| $i: 6; @while $i > 0 { .item-#{$i} { width: 2em * $i; } $i: $i - 2; }
|
=>
1 2 3 4 5 6 7 8 9
| .item-6 { width: 12em; } .item-4 { width: 8em; } .item-2 { width: 4em; }
|
函数指令
1 2 3 4 5 6 7
| $grid-width: 40px; $gutter-width: 10px; @function grid-width($n) { @return $n * $grid-width + ($n - 1) * $gutter-width; } #sidebar { width: grid-width(5); }
|
=>
1 2 3
| #sidebar { width: 240px; }
|
输出格式
- :nested 嵌套
- :expanded 更像是手写的样式
- :compact 每条 CSS 规则只占一行,包含其下的所有属性
- :compressed 删除所有无意义的空格、空白行、以及注释,力求将文件体积压缩到最小