前言
Sass 是一种编译为 CSS 的样式表语言。它允许您使用变量、嵌套规则、mixin、函数等,所有这些都使用完全兼容 CSS 的语法。
变量(Variables)
Sass的变量很简单: 你只要将值赋值给一个以$
开头的变量名,就可以使用该变量代替值。
例子:
$base-color: #c6538c;
$border-dark: rgba($base-color, 0.88);
.alert {
border: 1px solid $border-dark;
}
编译后:
.alert {
border: 1px solid rgba(198, 83, 140, 0.88);
}
默认值(!defalut)
如果分配给变量的值后面添加了 !default
标志 ,这意味着该变量如果已经赋值,那么它不会被重新赋值,但是,如果它尚未赋值,那么它会被赋予新的给定值。
$const: "Hi";
$const: "hello" !default;
div{
const: $const;
}
编译后:
div {
const: "Hi";
}
数据类型
- 数字,
1rem、2vh、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)
;
插值(Interpolation)
例子1:
@mixin corner-icon($name, $top-or-bottom, $left-or-right) {
.icon-#{$name} {
background-image: url("/icons/#{$name}.svg");
position: absolute;
#{$top-or-bottom}: 0;
#{$left-or-right}: 0;
}
}
@include corner-icon("mail", top, left);
编译后:
.icon-mail {
background-image: url("/icons/mail.svg");
position: absolute;
top: 0;
left: 0;
}
@规则
控制流
@if
和@else
例子:
@use "sass:math";
@mixin triangle($size, $color, $direction) {
height: 0;
width: 0;
border-color: transparent;
border-style: solid;
border-width: math.div($size, 2);
@if $direction == up {
border-bottom-color: $color;
} @else if $direction == right {
border-left-color: $color;
} @else if $direction == down {
border-top-color: $color;
} @else if $direction == left {
border-right-color: $color;
} @else {
@error "Unknown direction #{$direction}.";
}
}
.next {
@include triangle(5px, black, right);
}
@each
例子:
$sizes: 40px, 50px, 80px;
@each $size in $sizes {
.icon-#{$size} {
font-size: $size;
height: $size;
width: $size;
}
}
编译后:
.icon-40px {
font-size: 40px;
height: 40px;
width: 40px;
}
.icon-50px {
font-size: 50px;
height: 50px;
width: 50px;
}
.icon-80px {
font-size: 80px;
height: 80px;
width: 80px;
}
使用maps
例子:
$breakpoint-max: 1680px;
$breakpoint-xxl: 1440px;
$breakpoint-xlg: 1280px;
$breakpoint-lg: 960px;
$breakpoint-md: 768px;
$breakpoint-sm: 480px;
$maps: (
'sm': #{$breakpoint-sm},
'md': #{$breakpoint-md},
'lg': #{$breakpoint-lg},
'xlg': #{$breakpoint-xlg},
'xxl': #{$breakpoint-xxl},
'max': #{$breakpoint-max},
);
@each $p, $w in $maps {
.block-#{$p} {
width: #{$w};
}
}
编译后:
.block-sm {
width: 480px;
}
.block-md {
width: 768px;
}
.block-lg {
width: 960px;
}
.block-xlg {
width: 1280px;
}
.block-xxl {
width: 1440px;
}
.block-max {
width: 1680px;
}
解构
$icons:
"eye" "\f112" 12px,
"start" "\f12e" 16px,
"stop" "\f12f" 10px;
@each $name, $glyph, $size in $icons {
.icon-#{$name}:before {
display: inline-block;
font-family: "Icon Font";
content: $glyph;
font-size: $size;
}
}
@for
例子:
$base-color: #036;
@for $i from 1 through 3 {
ul:nth-child(3n + #{$i}) {
background-color: lighten($base-color, $i * 5%);
}
}
`@while
@use "sass:math";
@function scale-below($value, $base, $ratio: 1.618) {
@while $value > $base {
$value: math.div($value, $ratio);
}
@return $value;
}
$normal-font-size: 16px;
sup {
font-size: scale-below(20px, 16px);
}
@use
从其他Sass样式表加载mixin,function和变量,并将来自多个样式表的CSS组合在一起。通过@use
加载的称为模块。也可以从内建模块中加载。
例子:
// styles/_lists.scss
ul, ol {
text-align: left;
& & {
padding: {
bottom: 0;
left: 0;
}
}
}
// styles/index.scss
@use './_lists';
加载成员
// src/_corners.scss
$radius: 3px;
@mixin rounded {
border-radius: $radius;
}
// style.scss
@use "src/corners";
.button {
@include corners.rounded;
padding: 5px + corners.$radius;
}
设置命名空间
// style.scss
@use "src/corners" as c;
.button {
@include c.rounded;
padding: 5px + c.$radius;
}
也可以使用*
,但这种方式可能导致命名冲突,还是少用的好。
// style.scss
@use "src/corners" as *;
.button {
@include rounded;
padding: 5px + $radius;
}
私有成员
私用成员以-
或_
开头
// src/_corners.scss
$-radius: 3px;
@mixin rounded {
border-radius: $-radius;
}
// style.scss
@use "src/corners";
.button {
@include corners.rounded;
// 报错 $-radius 属于私有成员,在`_corners.scss`是不可以直接访问的
padding: 5px + corners.$-radius;
}
配置变量
我们可以使用!default
标识一个变量使得其可以配置,然后通过@use <url> with (<variable>: <value>, <variable>: <value>)
的方式来配置变量。
// _library.scss
$black: #000 !default;
$border-radius: 0.25rem !default;
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;
code {
border-radius: $border-radius;
box-shadow: $box-shadow;
}
// style.scss
@use 'library' with (
$black: #222,
$border-radius: 0.1rem
);
编译后:
code {
border-radius: 0.1rem;
box-shadow: 0 0.5rem 1rem rgba(34, 34, 34, 0.15);
}
@forward
@forward
语句能够引入另一个模块的所有变量、mixins
和函数,将它们间接作为以后模块的API
裸露进来,不会真的在以后模块减少代码。不同于 @use
, @forward
不能给变量增加命名空间。
用法
留神,此时生成的bootstrap.css
文件中,是不蕴含functions
、variables
、mixins
代码的,也不能间接在bootstrap.scss
文件中应用这些模块。而是需要在另一个文件中 @import 'bootstrap'
或者 @use bootstrap
模块,再去应用这些办法。bootstrap.scss
文件相似于一个传输中转站,把上下游的成员变量无缝连接起来。
/* bootstrap.scss */
@forward"functions";
@forward"variables";
@forward"mixins";
添加前缀
// src/_list.scss
@mixin reset {
margin: 0;
padding: 0;
list-style: none;
}
// bootstrap.scss
@forward "src/list" as list-*;
// styles.scss
@use "bootstrap";
li {
@include bootstrap.list-reset;
}
控制可见性 show/hide
使用 show
和 hide
,能够决定模块中的哪些成员对引入后的模板可见。对暗藏的变量,在上游文件中不能够应用,相当于模块公有成员。
// src/_list.scss
$horizontal-list-gap: 2em;
@mixin list-reset {
margin: 0;
padding: 0;
list-style: none;
}
@mixin list-horizontal {
@include list-reset;
li {
display: inline-block;
margin: {
left: -2px;
right: $horizontal-list-gap;
}
}
}
// bootstrap.scss
@forward "src/list" hide list-reset, $horizontal-list-gap;
配置变量
跟@use
用法差不多。区别是@forward
可以!default
标识。
// _library.scss
$black: #000 !default;
$border-radius: 0.25rem !default;
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;
code {
border-radius: $border-radius;
box-shadow: $box-shadow;
}
// _opinionated.scss
@forward 'library' with (
$black: #222 !default,
$border-radius: 0.1rem !default
);
// style.scss
@use 'opinionated' with ($black: #333);
@import
现在推荐使用@use
代替@import
。这里就不展开说明了。
@mixin和@include
用法
@mixin mixin-name() {
/* css 申明 */
}
// 应用
@include mixin-name;
例子:
@mixin reset-list {
margin: 0;
padding: 0;
list-style: none;
}
@mixin horizontal-list {
@include reset-list;
li {
display: inline-block;
margin: {
left: -2px;
right: 2em;
}
}
}
nav ul {
@include horizontal-list;
}
参数
@mixin corner-icon($name, $top-or-bottom, $left-or-right) {
.icon-#{$name} {
background-image: url("/icons/#{$name}.svg");
position: absolute;
#{$top-or-bottom}: 0;
#{$left-or-right}: 0;
}
}
@include corner-icon("mail", top, left);
可选参数
@mixin replace-text($image, $x: 50%, $y: 50%) {
text-indent: -99999em;
overflow: hidden;
text-align: left;
background: {
image: $image;
repeat: no-repeat;
position: $x $y;
}
}
.mail-icon {
@include replace-text(url("/images/mail.svg"), 0);
}
指定参数
@mixin square($size: 16px, $radius: 0) {
width: $size;
height: $size;
border-radius: $radius;
}
.avatar {
@include square($radius: 4px);
}
编译后:
.avatar {
width: 16px;
height: 16px;
border-radius: 4px;
}
不定参数
在mixin中最后一个变量使用...
结尾
例子:
@mixin order($height, $selectors...) {
@for $i from 0 to length($selectors) {
#{nth($selectors, $i + 1)} {
position: absolute;
height: $height;
margin-top: $i * $height;
}
}
}
@include order(150px, "input.name", "input.address", "input.zip");
@content
@mixin inline-animation($duration) {
$name: inline-#{unique-id()};
@keyframes #{$name} {
@content;
}
animation-name: $name;
animation-duration: $duration;
animation-iteration-count: infinite;
}
.pulse {
@include inline-animation(2s) {
from { background-color: yellow }
to { background-color: red }
}
}
编译后:
.pulse {
animation-name: inline-uoljdfspu;
animation-duration: 2s;
animation-iteration-count: infinite;
}
@keyframes inline-uoljdfspu {
from {
background-color: yellow;
}
to {
background-color: red;
}
}
@function
例子:
@function square($base) {
@return $base * $base * 1px;
}
.sidebar {
float: left;
margin-left: square(4);
}
@function
的可选参数、指定参数和不定参数用法和@mixin
类似,这里不展开了。
@return
@return
只容许在@function
内应用,和js
一样,遇到return
就会返回。
@extend
例子:
.error {
border: 1px #f00;
background-color: #fdd;
&--serious {
@extend .error;
border-width: 3px;
}
}
编译后:
.error, .error--serious {
border: 1px #f00;
background-color: #fdd;
}
.error--serious {
border-width: 3px;
}
@at-root
@at-root
用来跳出嵌套,可以结合without
和with
关键字使用。
//没有跳出
.parent-1 {
color:#f00;
.child {
width:100px;
}
}
//单个选择器跳出
.parent-2 {
color:#f00;
@at-root .child {
width:200px;
}
}
//多个选择器跳出
.parent-3 {
background:#f00;
@at-root {
.child1 {
width:300px;
}
.child2 {
width:400px;
}
}
}
编译后:
.parent-1 {
color: #f00;
}
.parent-1 .child {
width: 100px;
}
.parent-2 {
color: #f00;
}
.child {
width: 200px;
}
.parent-3 {
background: #f00;
}
.child1 {
width: 300px;
}
.child2 {
width: 400px;
}
@without
和with
默认@at-root
只会跳出选择器嵌套,而不能跳出@media
或@support
,如果要跳出这两种,则需应用@at-root (without: media)
或@at-root (without: support)
,@at-root
的关键词有四个:
all
示意所有;rule
示意惯例css
选择器;media
示意media
;support
示意support
(@support
次要是用于检测浏览器是否反对css
的某个属性)。
默认的@at-root
是@at-root (without:rule)
/*跳出父级元素嵌套*/
@media print {
.parent1{
color:#f00;
@at-root .child1 {
width:200px;
}
}
}
/*跳出media嵌套,父级无效*/
@media print {
.parent2{
color:#f00;
@at-root (without: media) {
.child2 {
width:200px;
}
}
}
}
/*跳出media和父级*/
@media print {
.parent3{
color:#f00;
@at-root (without: all) {
.child3 {
width:200px;
}
}
}
}
编译后:
/*跳出父级元素嵌套*/
@media print {
.parent1 {
color: #f00;
}
.child1 {
width: 200px;
}
}
/*跳出media嵌套,父级无效*/
@media print {
.parent2 {
color: #f00;
}
}
.parent2 .child2 {
width: 200px;
}
/*跳出media和父级*/
@media print {
.parent3 {
color: #f00;
}
}
.child3 {
width: 200px;
}
内建模块(Built-In Modules)
sass:string
quote
string.quote($string)
quote($string) //=> string
index
string.index($string, $substring)
str-index($string, $substring) //=> number
insert
string.insert($string, $insert, $index)
str-insert($string, $insert, $index) //=> string
length
string.length($string)
str-length($string) //=> number
slice
string.slice($string, $start-at, $end-at: -1)
str-slice($string, $start-at, $end-at: -1) //=> string
split
string.split($string, $separator, $limit: null) //=> list
to-upper-case
string.to-upper-case($string)
to-upper-case($string) //=> string
to-lower-case
string.to-lower-case($string)
to-lower-case($string) //=> string
unique-id
string.unique-id()
unique-id() //=> string
unquote
string.unquote($string)
unquote($string) //=> string
sass:list
append
append($list, $val, $separator: auto) //=> list
list.append($list, $val, $separator: auto)
例子:
@debug list.append(10px 20px, 30px); // 10px 20px 30px
@debug list.append((blue, red), green); // blue, red, green
@debug list.append(10px 20px, 30px 40px); // 10px 20px (30px 40px)
@debug list.append(10px, 20px, $separator: comma); // 10px, 20px
@debug list.append((blue, red), green, $separator: space); // blue red green
index
list.append($list, $val, $separator: auto)
append($list, $val, $separator: auto) //=> list
例子:
@debug list.index(1px solid red, 1px); // 1
@debug list.index(1px solid red, solid); // 2
@debug list.index(1px solid red, dashed); // null
is-bracketed
list.is-bracketed($list)
is-bracketed($list) //=> boolean
返回值是否带方括号
例子:
@debug list.is-bracketed(1px 2px 3px); // false
@debug list.is-bracketed([1px, 2px, 3px]); // true
join
list.join($list1, $list2, $separator: auto, $bracketed: auto)
join($list1, $list2, $separator: auto, $bracketed: auto) //=> list
例子:
@debug list.join(10px 20px, 30px 40px); // 10px 20px 30px 40px
@debug list.join((blue, red), (#abc, #def)); // blue, red, #abc, #def
@debug list.join(10px, 20px); // 10px 20px
@debug list.join(10px, 20px, $separator: comma); // 10px, 20px
@debug list.join((blue, red), (#abc, #def), $separator: space); // blue red #abc #def
@debug list.join([10px], 20px); // [10px 20px]
@debug list.join(10px, 20px, $bracketed: true); // [10px 20px]
length
list.length($list)
length($list) //=> number
返回列表的长度
例子:
@debug list.length(10px); // 1
@debug list.length(10px 20px 30px); // 3
@debug list.length((width: 10px, height: 20px)); // 2
separator
list.separator($list)
list-separator($list) //=> unquoted string
例子:
@debug list.separator(1px 2px 3px); // space
@debug list.separator(1px, 2px, 3px); // comma
@debug list.separator('Helvetica'); // space
@debug list.separator(()); // space
nth
list.nth($list, $n)
nth($list, $n)
例子:
@debug list.nth(10px 12px 16px, 2); // 12px
@debug list.nth([line1, line2, line3], -1); // line3
set-nth
list.set-nth($list, $n, $value)
set-nth($list, $n, $value) //=> list
例子:
@debug list.set-nth(10px 20px 30px, 1, 2em); // 2em 20px 30px
@debug list.set-nth(10px 20px 30px, -1, 8em); // 10px, 20px, 8em
@debug list.set-nth((Helvetica, Arial, sans-serif), 3, Roboto); // Helvetica, Arial, Roboto
slash
list.slash($elements...) //=> list
例子:
@debug list.slash(1px, 50px, 100px); // 1px / 50px / 100px
zip
list.zip($lists...)
zip($lists...) //=> list
例子:
@debug list.zip(10px 50px 100px, short mid long); // 10px short, 50px mid, 100px long
@debug list.zip(10px 50px 100px, short mid); // 10px short, 50px mid
sass:map
deep-merge
map.deep-merge($map1, $map2) //=> map
例子:
$helvetica-light: (
"weights": (
"lightest": 100,
"light": 300
)
);
$helvetica-heavy: (
"weights": (
"medium": 500,
"bold": 700
)
);
@debug map.deep-merge($helvetica-light, $helvetica-heavy);
// (
// "weights": (
// "lightest": 100,
// "light": 300,
// "medium": 500,
// "bold": 700
// )
// )
@debug map.merge($helvetica-light, $helvetica-heavy);
// (
// "weights": (
// "medium: 500,
// "bold": 700
// )
// )
deep-remove
map.deep-remove($map, $key, $keys...) //=> map
例子:
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
@debug map.deep-remove($font-weights, "regular");
// ("medium": 500, "bold": 700)
$fonts: (
"Helvetica": (
"weights": (
"regular": 400,
"medium": 500,
"bold": 700
)
)
);
@debug map.deep-remove($fonts, "Helvetica", "weights", "regular");
// (
// "Helvetica": (
// "weights: (
// "medium": 500,
// "bold": 700
// )
// )
// )
get
map.get($map, $key, $keys...)
map-get($map, $key, $keys...)
例子:
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
@debug map.get($font-weights, "medium"); // 500
@debug map.get($font-weights, "extra-bold"); // null
$fonts: (
"Helvetica": (
"weights": (
"regular": 400,
"medium": 500,
"bold": 700
)
)
);
@debug map.get($fonts, "Helvetica", "weights", "regular"); // 400
@debug map.get($fonts, "Helvetica", "colors"); // null
has-key
map.has-key($map, $key, $keys...)
map-has-key($map, $key, $keys...) //=> boolean
例子:
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
@debug map.has-key($font-weights, "regular"); // true
@debug map.has-key($font-weights, "bolder"); // false
$fonts: (
"Helvetica": (
"weights": (
"regular": 400,
"medium": 500,
"bold": 700
)
)
);
@debug map.has-key($fonts, "Helvetica", "weights", "regular"); // true
@debug map.has-key($fonts, "Helvetica", "colors"); // false
keys
merge
remove
set
values
更多内建模块函数见Sass官网