Sass 是一款強(qiáng)化 CSS 的輔助工具躯畴,它在 CSS 語法的基礎(chǔ)上增加了變量 (variables)民鼓、嵌套 (nested rules)、混合 (mixins)蓬抄、導(dǎo)入 (inline imports) 等高級功能丰嘉,這些拓展令 CSS 更加強(qiáng)大與優(yōu)雅。
兩種語法格式格式:1.scss 2.sass(縮進(jìn)代替花括號)嚷缭,可以相互導(dǎo)入和轉(zhuǎn)換
嵌套選擇器
父選擇器&
當(dāng)給某個元素設(shè)定?hover?樣式時饮亏,或者當(dāng)?body?元素有某個 classname 時耍贾,可以用?&?代表嵌套規(guī)則外層的父選擇器。
&?必須作為選擇器的第一個字符路幸,其后可以跟隨后綴生成復(fù)合的選擇器荐开,例如
屬性嵌套
?????? 有些 CSS 屬性遵循相同的命名空間 (namespace),比如?font-family, font-size, font-weight?都以?font?作為屬性的命名空間简肴。命名空間也可以包含自己的屬性值晃听,例如:
注釋
Sass 支持標(biāo)準(zhǔn)的 CSS 多行注釋?/* */,以及單行注釋?//砰识,前者會 被完整輸出到編譯后的 CSS 文件中能扒,而后者則不會
將?!?作為多行注釋的第一個字符表示在壓縮輸出模式下保留這條注釋并輸出到 CSS 文件中,通常用于添加版權(quán)信息仍翰。
插值語句 (interpolation) 也可寫進(jìn)多行注釋中輸出變量值:
SassScript
nteractive Shell
可以在命令行中測試 SassScript 的功能赫粥。在命令行中輸入?sass -i观话,然后輸入想要測試的SassScript 查看輸出結(jié)果:
數(shù)據(jù)類型
SassScript 支持 6 種主要的數(shù)據(jù)類型:
數(shù)字予借,1, 2, 13, 10px
字符串,有引號字符串與無引號字符串频蛔,"foo", 'bar', baz
顏色灵迫,blue, #04a3f9, rgba(255,0,0,0.5)
布爾型,true, false
空值晦溪,null
數(shù)組 (list)瀑粥,用空格或逗號作分隔符,1.5em 1em 0 2em, Helvetica, Arial, sans-serif
maps, 相當(dāng)于 JavaScript 的 object三圆,(key1: value1, key2: value2)
運算
SassScript 支持?jǐn)?shù)字的加減乘除狞换、取整等運算 (+, -, *, /, %),如果必要會在不同單位間轉(zhuǎn)換值舟肉。
除法運算/
如果需要使用變量修噪,同時又要確保?/?不做除法運算而是完整地編譯到 CSS 文件中,只需要用?#{}?插值語句將變量包裹路媚。
顏色值運算
顏色值的運算是分段計算進(jìn)行的黄琼,也就是分別計算紅色,綠色整慎,以及藍(lán)色的值:
需要注意的是脏款,如果顏色值包含 alpha channel(rgba 或 hsla 兩種顏色值),必須擁有相等的 alpha 值才能進(jìn)行運算裤园,因為算術(shù)運算不會作用于 alpha 值撤师。
顏色值的 alpha channel 可以通過?opacify?或?transparentize?兩個函數(shù)進(jìn)行調(diào)整。
字符串運算
+?可用于連接字符串拧揽。注意剃盾,如果有引號字符串(位于?+?左側(cè))連接無引號字符串,運算結(jié)果是有引號的,相反万俗,無引號字符串(位于?+?左側(cè))連接有引號字符串湾笛,運算結(jié)果則沒有引號。
空的值被視作插入了空字符串:
布爾運算
SassScript 支持布爾型的?and?or?以及?not?運算闰歪。
插值語句#{}
變量$
SassScript 最普遍的用法就是變量嚎研,變量以美元符號開頭,賦值方法與 CSS 屬性的寫法一樣:
變量定義!default
@-Rules 與指令
@import
Sass 拓展了?@import?的功能库倘,允許其導(dǎo)入 SCSS 或 Sass 文件临扮。被導(dǎo)入的文件將合并編譯到同一個 CSS 文件中,另外教翩,被導(dǎo)入的文件中所包含的變量或者混合指令 (mixin) 都可以在導(dǎo)入的文件中使用杆勇。
通常,@import?尋找 Sass 文件并將其導(dǎo)入饱亿,但在以下情況下蚜退,@import?僅作為普通的 CSS 語句,不會導(dǎo)入任何 Sass 文件彪笼。
文件拓展名是?.css钻注;
文件名以?http://?開頭;
文件名是?url()配猫;
@import?包含 media queries幅恋。
如果不在上述情況內(nèi),文件的拓展名是?.scss?或?.sass泵肄,則導(dǎo)入成功捆交。沒有指定拓展名,Sass 將會試著尋找文件名相同腐巢,拓展名為?.scss?或?.sass?的文件并將其導(dǎo)入品追。
Sass 允許同時導(dǎo)入多個文件
@import "rounded-corners", "text-shadow";
導(dǎo)入文件也可以使用?#{ }?插值語句,但不是通過變量動態(tài)導(dǎo)入 Sass 文件系忙,只能作用于 CSS 的?url()?導(dǎo)入方式:
$family: unquote("Droid+Sans");
@import url("http://fonts.googleapis.com/css?family=\#{$family}");
編譯為
@import url("http://fonts.googleapis.com/css?family=Droid+Sans");
分音
如果需要導(dǎo)入 SCSS 或者 Sass 文件诵盼,但又不希望將其編譯為 CSS,只需要在文件名前添加下劃線银还,這樣會告訴 Sass 不要編譯這些文件风宁,但導(dǎo)入語句中卻不需要添加下劃線。
例如蛹疯,將文件命名為?_colors.scss戒财,便不會編譯?_colours.css?文件。
@import "colors";
上面的例子捺弦,導(dǎo)入的其實是?_colors.scss?文件
注意饮寞,不可以同時存在添加下劃線與未添加下劃線的同名文件孝扛,添加下劃線的文件將會被忽略。
嵌套@import
大多數(shù)情況下幽崩,一般在文件的最外層(不在嵌套規(guī)則內(nèi))使用?@import苦始,其實,也可以將?@import?嵌套進(jìn) CSS 樣式或者?@media?中慌申,與平時的用法效果相同陌选,只是這樣導(dǎo)入的樣式只能出現(xiàn)在嵌套的層中。
假設(shè)example.scss 文件包含以下樣式:
.example {
? color: red;
}
然后導(dǎo)入到?#main?樣式內(nèi)
#main {
? @import "example";
}
將會被編譯為
#main .example {
? color: red;
}
@extend
在設(shè)計網(wǎng)頁的時候常常遇到這種情況:一個元素使用的樣式與另一個元素完全相同蹄溉,但又添加了額外的樣式咨油。通常會在 HTML 中給元素定義兩個 class,一個通用樣式柒爵,一個特殊樣式役电。
.error {
? border: 1px #f00;
? background-color: #fdd;
}
.seriousError {
? @extend .error;
? border-width: 3px;
}
上面代碼的意思是將?.error?下的所有樣式繼承給?.seriousError,border-width: 3px;?是單獨給?.seriousError?設(shè)定特殊樣式棉胀,這樣法瑟,使用?.seriousError?的地方可以不再使用?.error。
其他使用到?.error?的樣式也會同樣繼承給?.seriousError膏蚓,例如瓢谢,另一個樣式?.error.intrusion?使用了?hacked.png?做背景畸写,<div
class="seriousError intrusion">?也同樣會使用?hacked.png?背景驮瞧。
.error.intrusion {
? background-image: url("/image/hacked.png");
}
占位符選擇器%
Sass 引入了“占位符選擇器”
(placeholder selectors),看起來很像普通的?id?或?class?選擇器枯芬,只是?#?或?.?被替換成了?%论笔。可以像 class 或者 id 選擇器那樣使用千所,當(dāng)它們單獨使用時狂魔,不會被編譯到 CSS 文件中。
// This ruleset won't be rendered on its own.
#context a%extreme {
? color: blue;
? font-weight: bold;
? font-size: 2em;
}
占位符選擇器需要通過延伸指令使用淫痰,用法與 class 或者 id 選擇器一樣最楷,被延伸后,占位符選擇器本身不會被編譯待错。
.notice {
? @extend %extreme;
}
編譯為
#context a.notice {
? color: blue;
? font-weight: bold;
? font-size: 2em; }
!optional 聲明
如果?@extend?失敗會收到錯誤提示籽孙,比如,這樣寫?a.important {@extend .notice}火俄,當(dāng)沒有?.notice?選擇器時犯建,將會報錯,只有?h1.notice?包含?.notice?時也會報錯瓜客,因為?h1?與?a?沖突适瓦,會生成新的選擇器竿开。
如果要求?@extend?不生成新選擇器,可以通過?!optional?聲明達(dá)到這個目的玻熙,例如:
a.important {
? @extend .notice !optional;
}
在指令中延伸
在指令中使用?@extend?時(比如在?@media?中)有一些限制:Sass 不可以將?@media?層外的 CSS 規(guī)則延伸給指令層內(nèi)的 CSS否彩,這樣會生成大量的無用代碼。也就是說嗦随,如果在?@media?(或者其他 CSS 指令)中使用?@extend胳搞,必須延伸給相同指令層中的選擇器。
下面的例子是可行的:
@media print {
? .error {
??? border: 1px #f00;
??? background-color: #fdd;
? }
? .seriousError {
??? @extend .error;
??? border-width: 3px;
? }
}
但不可以這樣:
.error {
? border: 1px #f00;
? background-color: #fdd;
}
@media print {
? .seriousError {
??? // INVALID EXTEND: .error is used outside of the "@media print" directive
??? @extend .error;
??? border-width: 3px;
? }
}
@at-root (without: ...) and @at-root (with: ...)
默認(rèn)情況下称杨,@at-root 只排除選擇器肌毅。但是,也可以使用 @at-root 移出嵌套指令(例如 @media)姑原。例如:
@media print {
? .page {
??? width: 8in;
??? @at-root (without: media) {
????? color: red;
??? }
? }
}
編譯為
@media print {
? .page {
??? width: 8in;
? }
}
.page {
? color: red;
}
@debug
@debug 指令將 SassScript 表達(dá)式的值打印到標(biāo)準(zhǔn)錯誤輸出流悬而。它對于調(diào)試具有復(fù)雜 SassScript 的 Sass 文件很有用。例如:
@debug 10em + 12em;
編譯為
Line 1 DEBUG: 22em
@warn
@error
控制指令
@if
當(dāng)?@if?的表達(dá)式返回值不是?false?或者?null?時锭汛,條件成立笨奠,輸出?{}?內(nèi)的代碼:
p {
? @if 1 + 1 == 2 { border: 1px solid; }
? @if 5 < 3 { border: 2px dotted; }
? @if null? { border: 3px double; }
}
編譯為
p {
? border: 1px solid; }
@for
@for?指令可以在限制的范圍內(nèi)重復(fù)輸出格式,每次按要求(變量的值)對輸出結(jié)果做出變動唤殴。這個指令包含兩種格式:@for $var from <start> through
<end>般婆,或者?@for $var from <start> to <end>,區(qū)別在于?through?與?to?的含義:當(dāng)使用?through?時朵逝,條件范圍包含?<start>?與?<end>?的值蔚袍,而使用?to?時條件范圍只包含?<start>?的值不包含?<end>?的值。另外配名,$var?可以是任何變量啤咽,比如?$i;<start>?和?<end>?必須是整數(shù)值渠脉。
@for $i from 1 through 3 {
? .item-#{$i} { width: 2em * $i; }
}
編譯為
.item-1 {
? width: 2em; }
.item-2 {
? width: 4em; }
.item-3 {
? width: 6em; }
@each
@each?指令的格式是?$var in <list>,?$var?可以是任何變量名宇整,比如?$length?或者?$name,而?<list>?是一連串的值芋膘,也就是值列表鳞青。
@each?將變量?$var?作用于值列表中的每一個項目,然后輸出結(jié)果为朋,例如:
@each $animal in puma, sea-slug, egret, salamander {
? .#{$animal}-icon {
??? background-image: url('/images/#{$animal}.png');
? }
}
編譯為
.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 指令還可以使用多個變量臂拓,如 @each $var1, $var2, ... in 。如果是列表列表潜腻,則子列表的每個元素都分配給相應(yīng)的變量埃儿。例如:
@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;
? }
}
編譯為
.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; }
@while
@while?指令重復(fù)輸出格式直到表達(dá)式返回結(jié)果為?false。這樣可以實現(xiàn)比?@for?更復(fù)雜的循環(huán)融涣,只是很少會用到童番。例如:
$i: 6;
@while $i > 0 {
? .item-#{$i} { width: 2em * $i; }
? $i: $i - 2;
}
.item-6 {
? width: 12em; }
.item-4 {
? width: 8em; }
.item-2 {
? width: 4em; }
混合指令@mixin
@mixin large-text {
? font: {
??? family: Arial;
??? size: 20px;
??? weight: bold;
? }
? color: #ff0000;
}
引用混合樣式@include
.page-title {
? @include large-text;
? padding: 4px;
? margin-top: 10px;
}
也可以在最外層引用混合樣式精钮,不會直接定義屬性,也不可以使用父選擇器剃斧。
@mixin silly-links {
? a {
??? color: blue;
??? background-color: red;
? }
}
@include silly-links;
編譯為
a {
? color: blue;
? background-color: red; }
參數(shù)
@mixin sexy-border($color, $width) {
? border: {
??? color: $color;
??? width: $width;
??? style: dashed;
? }
}
p { @include sexy-border(blue, 1in); }
編譯為
p {
? border-color: blue;
? border-width: 1in;
? border-style: dashed; }
混合指令也可以使用給變量賦值的方法給參數(shù)設(shè)定默認(rèn)值轨香,然后,當(dāng)這個指令被引用的時候幼东,如果沒有給參數(shù)賦值臂容,則自動使用默認(rèn)值
混合指令也可以使用關(guān)鍵詞參數(shù),上面的例子也可以寫成:
p { @include sexy-border($color: blue); }
h1 { @include sexy-border($color: blue, $width: 2in); }
參數(shù)變量
有時根蟹,不能確定混合指令需要使用多少個參數(shù)脓杉,比如一個關(guān)于?box-shadow?的混合指令不能確定有多少個 'shadow' 會被用到。這時简逮,可以使用參數(shù)變量?…?聲明(寫在參數(shù)的最后方)告訴 Sass 將這些參數(shù)視為值列表處理:
@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);
}
編譯為
.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;
}
參數(shù)變量也可以用在引用混合指令的時候 (@include)球散,與平時用法一樣,將一串值列表中的值逐條作為參數(shù)引用:
@mixin colors($text, $background, $border) {
? color: $text;
? background-color: $background;
? border-color: $border;
}
$values: #ff0000, #00ff00, #0000ff;
.primary {
? @include colors($values...);
}
編譯為
.primary {
? color: #ff0000;
? background-color: #00ff00;
? border-color: #0000ff;
}
向混合樣式中導(dǎo)入內(nèi)容@content
在引用混合樣式的時候散庶,可以先將一段代碼導(dǎo)入到混合指令中蕉堰,然后再輸出混合樣式,額外導(dǎo)入的部分將出現(xiàn)在?@content?標(biāo)志的地方:
@mixin apply-to-ie6-only {
? * html {
??? @content;
? }
}
@include apply-to-ie6-only {
? #logo {
??? background-image: url(/logo.gif);
? }
}
編譯為
* html #logo {
? background-image: url(/logo.gif);
}
為便于書寫悲龟,@mixin?可以用?=?表示屋讶,而?@include?可以用?+?表示(使用+時報錯)
函數(shù)指令@function
$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 相同,也可以傳遞若干個全局變量給函數(shù)作為參數(shù)须教。一個函數(shù)可以含有多條語句皿渗,需要調(diào)用?@return?輸出結(jié)果。
下面附上示例代碼:
<template>
??<div>
????<a>父選擇器&</a>
????<div?id="main">
??????main
??????<div?id="main-sidebar">復(fù)合的選擇器#main-sidebar</div>
??????<div?class="example">import導(dǎo)入到?#main?樣式內(nèi)</div>
????</div>
????<div?class="funky">屬性嵌套</div>
????<div?class="inter-shell">Interactive?Shell</div>
????<p>運算</p>
????<p?class="foo">插值語句?#{}</p>
????<div>
??????<div?class="error">錯誤</div>
??????<div?class="seriousError?intrusion">嚴(yán)重錯誤</div>
????</div>
????<div?id="context">
??????<a?class="notice">占位符</a>
????</div>
????<div?class="page">@at-root?(without:?...)?and?@at-root?(with:?...)</div>
????<P?id="test-p">@if</P>
????<div?v-for="(obj,?index)?in?items"?:key="index">
??????<div?:class="`item-${index?+?1}`">item{{?index?}}</div>
????</div>
????<div?class="page-title">混合@mixin</div>
????<div?id="sexy1">混合參數(shù)1</div>
????<div?id="sexy2">混合參數(shù)2</div>
????<div?id="logo">向混合樣式中導(dǎo)入內(nèi)容?@content</div>
????<div?id="sidebar">function</div>
??</div>
</template>
<script>
export?default?{
??data()?{
????return?{
??????items:?[1,?2,?3]
????}
??}
}
</script>
<style?lang="scss">
a?{
??font-weight:?bold;
??text-decoration:?none;
??&:hover?{
????text-decoration:?underline;
??}
??body.firefox?&?{
????font-weight:?normal;
??}
}
#main?{
??color:?black;
??&-sidebar?{
????border:?1px?solid;
??}
}
.funky?{
??font:?20px/24px?{
????family:?fantasy;
????weight:?bold;
??}
}
/*?多行注釋
多行注釋
?多行注釋*/
//??單行注釋
//??單行注釋
$version:?'1.2.3';
/*?This?CSS?is?generated?by?My?Snazzy?Framework?version?#{$version}.?*/
.inter-shell?{
??font-size:?10px?+?2px?+?2px;
??//?color:?#777?+?#777;?//失敗,在未來的版本會被遺棄没卸,推薦我們使用sass顏色函數(shù)代替
}
$width:?300px;
#main?{
??width:?$width;
}
p?{
??width:?1in?+?8pt;
}
//?p?{
//???font:?10px/8px;?//?Plain?CSS,?no?division
//???$width:?1000px;
//???width:?$width/2;?//?Uses?a?variable,?does?division
//???width:?round(1.5)?/?2;?//?Uses?a?function,?does?division
//???height:?(500px/2);?//?Uses?parentheses,?does?division
//???margin-left:?5px?+?8px/2px;?//?Uses?+,?does?division
//?}
//?p?{
//???$font-size:?12px;
//???$line-height:?30px;
//???font:?#{$font-size}/#{$line-height};
//?}
$translucent-red:?rgba(255,?0,?0,?0.5);
p?{
??color:?opacify($translucent-red,?0.3);
??background-color:?transparentize($translucent-red,?0.25);
}
//?p:before?{
//???content:?'Foo?'?+?Bar;
//???font-family:?sans-?+?'serif';
//?}
//?p:before?{
//???content:?'I?ate?#{5?+?10}?pies!';
//?}
//?$value:?null;
//?p:before?{
//???content:?'I?ate#{$value}pies!';
//?}
$name:?foo;
$attr:?border;
p.#{$name}?{
??#{$attr}-color:?blue;
??//?#{$attr}-width:?1px;
??//?#{$attr}-style:?solid;
}
$content:?'First?content';
$content:?'Second?content?'?!default;
$new_content:?'First?time?reference'?!default;
#main?{
??content:?$content;
??new-content:?$new_content;
}
#main?{
??@import?'./src/styles/example';?//文件命名時不帶.scss報錯
}
//?@import?'./src/styles/foo';
.error?{
??border:?1px?#f00?solid;
??background-color:?#fdd;
}
.seriousError?{
??@extend?.error;
??border-width:?3px;
}
.error.intrusion?{
??background-image:?url('../../assets/logo.png');
}
#context?a%extreme?{
??color:?blue;
??font-weight:?bold;
??font-size:?2em;
}
.notice?{
??@extend?%extreme;
??//?@extend?.notice?!optional;//沒理解
}
//?@media?print?{
//???.page?{
//?????width:?200px;
//?????@at-root?(without:?media)?{
//???????color:?red;
//?????}
//???}
//?}?//編譯后找不到media
@debug?10px?+?12px;?//在vscode下面的終端顯示
@warn?10px?+?12px;
//?@error?10px?+?12px;?//vscode會報錯
#test-p?{
??@if?1?+?1?>?2?{
????border:?1px?solid;
??}?@else?if?5?==?3?{
????border:?2px?dotted;
??}?@else?{
????border:?3px?double;
??}
}
@for?$i?from?1?through?3?{
??.item-#{$i}?{
????width:?2em?*?$i;
??}
}
@mixin?large-text?{
??font:?{
????family:?Arial;
????size:?20px;
????weight:?bold;
??}
??color:?#ff0000;
}
.page-title?{
??@include?large-text;
??padding:?4px;
??margin-top:?10px;
}
@mixin?sexy-border($color,?$width)?{
??border:?{
????color:?$color;
????width:?$width;
????style:?dashed;
??}
}
#sexy1?{
??@include?sexy-border(blue,?1px);
}
#sexy2?{
??@include?sexy-border(green,?2px);
}
@mixin?apply-to-ie6-only?{
??html?{
????@content;
??}
}
@include?apply-to-ie6-only?{
??#logo?{
????background-image:?url('../../assets/logo.png');
??}
}
$grid-width:?40px;
$gutter-width:?10px;
@function?grid-width($n)?{
??@return?$n?*?$grid-width?+?($n?-?1)?*?$gutter-width;
}
#sidebar?{
??width:?grid-width(5);
}
</style>