2015年10月20日
1.嵌套
Sass 中還提供了選擇器嵌套功能,但這也并不意味著你在 Sass 中的嵌套是無節(jié)制的,因?yàn)槟闱短椎膶蛹?jí)越深,編譯出來的 CSS 代碼的選擇器層級(jí)將越深,這往往是大家不愿意看到的一點(diǎn)。這個(gè)特性現(xiàn)在正被眾多開發(fā)者濫用。
Sass的嵌套分為3種:
a.選擇器嵌套
b.屬性嵌套
c.偽類嵌套
1、選擇器嵌套
假設(shè)我們有一段這樣的結(jié)構(gòu):
<header>
<nav>
<a href=“##”>Home</a>
<a href=“##”>About</a>
<a href=“##”>Blog</a>
</nav>
<header>
想選中header中的a標(biāo)簽,在寫CSS會(huì)這樣寫:
nav a {
color:red;
}
header nav a {
color:green;
}
那么在Sass中,就可以使用選擇器的嵌套來實(shí)現(xiàn):
nav {
a {
color: red;
header & {
color:green;
}
}
}
2.屬性嵌套
Sass中還提供屬性嵌套,CSS有一些屬性前綴相同,只是后綴不一樣,比如:border-top/border-right,與這個(gè)類似的還有margin、padding、font等屬性。假設(shè)你的樣式中用到了:
.box{
border-top: 1px solid red;
border-bottom: 1px soid green;
}
在Sass中可以這樣寫:
.box{
border:{
top: 1px solid red;
bottom: 1px solid green;
}
}
3.偽類嵌套
其實(shí)偽類嵌套和屬性嵌套非常相似,只不過他需要借助'&'符號(hào)一起配合使用。我們就拿經(jīng)典的"clearfix"為例吧:
.clearfix{
&: bofore,
&:after{
content:"";
display: table;
}
&:after{
clear: both;
overflow: hidden;
}
}
編譯出來的CSS:
.clearfix:before, .clearfix:after{
content: "";
display: table;
}
.clearfix:after{
clear:both;
overflow: hidden;
}
盡量避免選擇器選擇器嵌套
混合宏
如果你的整個(gè)網(wǎng)站中有幾處小樣式類似,比如顏色,字體等,在Sass可以使用變量來統(tǒng)一處理,那么這種選擇還是不錯(cuò)的。但當(dāng)你的樣式變得越來越復(fù)雜,需要重復(fù)使用大段的樣式時(shí),使用變量就無法達(dá)到我們的目的了。這個(gè)時(shí)候Sass中的混合宏就會(huì)變得非常有意義。
1.聲明混合宏
不帶參數(shù)的混合宏:
在Sass中,使用"@mixin"來聲明一個(gè)混合宏,如:
@mixin border-radius{
-webkit-border-radius: 5px;
border-radius: 5px;
}
其中@mixin是用來聲明混合宏的關(guān)鍵詞,有點(diǎn)類似CSS中的@media、@font-face一樣。border-radius是混合宏的名稱。大括號(hào)里面是復(fù)用的樣式代碼。
帶參數(shù)的混合宏:
除了一個(gè)不帶參數(shù)的混合宏之外,還可以在定義混合宏時(shí)帶有參數(shù),如:
@mixin border-radius($radius:5px){
-webkit-border-radius: $radius;
border-radius: $radius;
}
復(fù)雜的混合宏:
上面是一個(gè)簡(jiǎn)單的定義混合宏的方法,當(dāng)然,Sass中的混合宏還提供更為復(fù)雜的,你可以在大括號(hào)里面寫上帶有邏輯關(guān)系,幫助更好的做你想做的事,如:
@mixin box-shadow($shadow...){
@if length($shadow) >=1{
@include prefixer(box-shadow, $shadow);
} @else{
$shadow: 0 0 4px rgba(0, 0, 0, .3);
@include prefixer(box-shadow, $shadow);
}
}
這個(gè) box-shadow 的混合宏,帶有多個(gè)參數(shù),這個(gè)時(shí)候可以使用“ … ”來替代。簡(jiǎn)單的解釋一下,當(dāng) $shadow 的參數(shù)數(shù)量值大于或等于“ 1 ”時(shí),表示有多個(gè)陰影值,反之調(diào)用默認(rèn)的參數(shù)值“ 0 0 4px rgba(0,0,0,.3) ”。
2.調(diào)用混合宏
在Sass中通過@mixin關(guān)鍵詞聲明了一個(gè)混合宏,那么在實(shí)際調(diào)用中,其匹配了一個(gè)關(guān)鍵詞"@include"來調(diào)用聲明好的混合宏。例如在你的樣式中定義了一個(gè)圓角的混合宏"border-radius":
@mixin border-radius{
-webkit-border-radius: 3px;
border-radius: 3px;
}
在一個(gè)按鈕中要調(diào)用定義好的混合宏"border-radius", 可以這樣使用:
button{
@include border-radius;
}
這個(gè)時(shí)候編譯出來的CSS:
button{
-webkit-border-radius: 3px;
border-radius: 3px;
}
3.混合宏的參數(shù)
Sass的混合宏有一個(gè)強(qiáng)大的功能,可以傳參,那么在Sass中傳參主要有一下幾種情況:
A)傳一個(gè)不帶值的參數(shù)
在混合宏中,可以傳一個(gè)不帶任何值的參數(shù),比如:
@mixin border-radius($radius){
-weblit-border-radius: $radius;
border-radius: $radius;
}
在混合宏“border-radius”中定義了一個(gè)不帶任何值的參數(shù)“$radius”。
在調(diào)用的時(shí)候可以給這個(gè)混合宏傳一個(gè)參數(shù)值:
.box{
@include border-radius(3px);
}
這里表示給混合宏傳遞了一個(gè)"border-radius"的值為"3px"。
編譯出來的CSS:
.box{
-webkit-border-radius: 3px;
border-radius: 3px;
}
B)傳一個(gè)帶值的參數(shù)
在Sass的混合宏中,還可以給混合宏的參數(shù)傳一個(gè)默認(rèn)值,例如:
@mixin border-radius($radius:3px){
-webkit-border-radius: $radius;
border-radius: $radius;
}
在混合宏“border-radius”傳了一個(gè)參數(shù)“$radius”,而且給這個(gè)參數(shù)賦予了一個(gè)默認(rèn)值“3px”。
在調(diào)用類似這樣的混合宏時(shí),會(huì)多有一個(gè)機(jī)會(huì),假設(shè)你的頁面中的圓角很多地方都是“3px”的圓角,那么這個(gè)時(shí)候只需要調(diào)用默認(rèn)的混合宏“border-radius”:
.btn { @include border-radius;}
編譯出來的CSS:
.btn{
-webkit-border-radius: 3px;
border-radius: 3px;
}
但有的時(shí)候,頁面中有些元素的圓角值不一樣,那么可以隨機(jī)給混合宏傳值,如:
.box { @include border-radius(50%);}
編譯出來的CSS:
.box { -webkit-border-radius: 50%; border-radius: 50%;}
C)傳多個(gè)參數(shù)
Sass混合宏除了能傳一個(gè)參數(shù)之外,還可以傳多個(gè)參數(shù),如:
@mixin center($width, $height){
width: $width;
height: $height;
position: absolute;
top: 50%;
left: 50%;
margin-top: -($height)/2;
margin-left: -($width)/2;
}
在混合宏"center"就傳了多個(gè)參數(shù)。在實(shí)際調(diào)用和其調(diào)用其他混合宏是一樣的:
.box-center{
@include center(500px, 300px);
}
編譯出來的CSS:
.box-center{
width: 500px;
height: 300px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -150px;
margin-left: -250px;
}
有一個(gè)特別的參數(shù)"..."。當(dāng)混合宏傳的參數(shù)過多之時(shí),可以使用參數(shù)來替代,如:
@mixin box-shadow($shadows...){
@if length($shadows) >= 1{
-webkit-box-shadow: $shadows;
box-shadow: $shadows;
}@else{
$shadows: 0 0 2px rgba(#000, .25);
-webkit-box-shadow: $shadows;
box-shadow: $shadows;
}
}
在實(shí)際調(diào)用中:
.box{
@include box-shadow(0 0 1px rgba(#000, .5), 0 0 2px rgba(#000, .2));
}
編譯出來的CSS:
.box{
-webkit-box-shadow: 0 0 1px rgba(0, 0, 0 , 0.5), 0 0 2px rgba(0, 0, 0, 0.2);
box-shadow: 0 0 1px rgba(0, 0, 0 , 0.5), 0 0 2px rgba(0, 0, 0, 0.2);
}
D)混合宏的不足
混合宏在實(shí)際編碼中給我們帶來很多方便之處,特別是對(duì)于復(fù)用重復(fù)代碼塊。但其最大的不足之處是會(huì)生成冗余的代碼塊。比如在不同的地方調(diào)用一個(gè)相同的混合宏時(shí)。如:
@mixin border-radius{
-webkit-border-radius: 3px;
border-radius: 3px;
}
.box{
@include border-radius;
margin-bottom: 5px;
}
.btn{
@include border-radius;
}
示例在".box"和".btn"中都調(diào)用了定義好的"border-radius"混合宏。先來看編譯出來的CSS:
.box{
-webkit-border-radius: 3px;
border-radius: 3px;
margin-bottom: 5px;
}
.btn{
-webkit-border-radius: 3px;
border-radius: 3px;
}
上例明顯可以看出,Sass在調(diào)用相同的混合宏時(shí),并不能智能的將相同的樣式代碼塊合并在一起。這也是Sass的混合宏最不足之處。
擴(kuò)展/繼承
在Sass中通過關(guān)鍵詞"@extend"來繼承已存在的類樣式塊,從而實(shí)現(xiàn)代碼的繼承。如下所示:
//SCSS
.btn{
border:1px solid #ccc;
padding: 6px 10px;
font-size: 14px;
}
.btn-primary{
background-color: #f36;
color: #fff;
@extend .btn;
}
.btn-second{
background-color: orange;
color: #fff;
@extend .btn;
}
編譯出來之后:
//CSS
.btn, .btn-primary, .btn-second{
border: 1px solid #ccc;
padding: 6px 10px;
font-size: 14px;
}
.btn-primary{
background-color: #f36;
color: #fff;
}
.btn-second{
background-color: orange;
color: #fff;
}
從示例代碼可以看出,在Sass中的繼承,可以繼承類樣式塊中所有樣式代碼,而且編譯出來的CSS會(huì)將選擇器合并在一起,形成組合選擇器:
.btn, .btn-primary, .btn-second{
border: 1px solid #ccc;
padding: 6px 10px;
font-size: 14px;
}
占位符%placeholder
Sass中的占位符%placeholder功能是一個(gè)很強(qiáng)大、很實(shí)用的一個(gè)功能,他可以取代以前CSS中的基類造成的代碼冗余的情形。因?yàn)?placeholder聲明的代碼,如果不被@extend調(diào)用的話,不會(huì)產(chǎn)生任何代碼。示例:
%mt5{
margin-top: 5px;
}
%pt5{
padding-top: 5px;
}
這段代碼沒有被@extend調(diào)用,他并沒有產(chǎn)生任何代碼塊,只是靜靜的躺在你的某個(gè)SCSS文件中。只有通過@extend調(diào)用才會(huì)產(chǎn)生代碼:
//SCSS
%mt5{
margin-top: 5px;
}
%pt5{
padding-top: 5px;
}
.btn{
@extend %mt5;
@extend %pt5;
}
.block{
@extend %mt5;
span{
@expend %pt5;
}
}
編譯出來的CSS
//CSS
.btn, .block{
margin-top: 5px;
}
.btn, .block span{
padding-top: 5px;
}
從編譯出來的CSS代碼可以看出,通過@expend調(diào)用的占位符,編譯出來的代碼會(huì)將相同的代碼合并在一起。這也是我們希望看到的效果,也讓你的代碼變的更為干凈。
混合宏 VS 繼承 VS 占位符
a)混合宏的使用
如果你的代碼塊中涉及到變量,建議使用混合宏來創(chuàng)建相同的代碼塊。
b)Sass 繼承
如果你的代碼塊不需要傳任何變量參數(shù),而且有一個(gè)基類已在文件中存在,那么建議使用Sass繼承
c)占位符
編譯出來的 CSS 代碼和使用繼承基本上是相同,只是不會(huì)在代碼中生成占位符 mt 的選擇器。那么占位符和繼承的主要區(qū)別的,“占位符是獨(dú)立定義,不調(diào)用的時(shí)候是不會(huì)在 CSS 中產(chǎn)生任何代碼;繼承是首先有一個(gè)基類存在,不管調(diào)用與不調(diào)用,基類的樣式都將會(huì)出現(xiàn)在編譯出來的 CSS 代碼中。”
插值#{}
使用CSS預(yù)處理器語言的一個(gè)主要原因是想使用Sass獲得一個(gè)更好的結(jié)構(gòu)體系。比如說你想寫更干凈的、高效的和面向?qū)ο蟮腃SS。Sass中的插值就是重要的一部分。示例:
$properties: (margin, padding);
@mixin set-value($side, $value){
@each $prop in $properties{
#{$prop}-#{side}: $value;
}
}
.login-box{
@include set-value(top, 14px);
]
它可以讓變量和屬性工作的很完美,上面的代碼編譯成CSS:
.login-box{
margin-top: 14px;
padding-top: 14px;
}
這是Sass插值中的一個(gè)簡(jiǎn)單的實(shí)例。當(dāng)你想設(shè)置屬性值的時(shí)候你可以使用字符串插入進(jìn)來。另一個(gè)有用的用法是構(gòu)建一個(gè)選擇器。可以這樣使用:
@mixin generate-sizes($class, $small, $medium, $big){
.#{$class}-small {font-size: $small;}
.#{$class}-medium{font-size: $medium;}
.#{$class}-big{font-size: $big;}
}
@include generate-sizes("header-text", 12px, 20px, 40px);
編譯出來的CSS:
.header-text-small {font-size:12px;}
.header-text-medium {font-size:20px;}
.header-text-big{font-size: 40px;}
$margin-big: 40px;
$margin-medium: 20px;
$margin-small: 12px;
@mixin set-value($size){
margin-top: $margin-#{$size};
}
.login-box{
@include set-value(big);
}
上面的Sass代碼編譯出來,你會(huì)得到下面的信息:
error style.scss (Line 5: Undefined variable: “$margin-".)
所以,#{}語法并不是隨處可用,你也不能在mixin中調(diào)用:
@mixin updated-status {
margin-top: 20px;
background: #F00;
}
$flag: "status";
.navigation {
@include updated-#{$flag};
}
上面的代碼在編譯成 CSS 時(shí)同樣會(huì)報(bào)錯(cuò):
error style.scss (Line 7: Invalid CSS after "...nclude updated-": expected "}", was "#{$flag};")
幸運(yùn)的是,可以使用 @extend 中使用插值。例如:
%updated-status {
margin-top: 20px;
background: #F00;
}
.selected-status {
font-weight: bold;
}
$flag: "status";
.navigation {
@extend %updated-#{$flag};
@extend .selected-#{$flag};
}
上面的 Sass 代碼是可以運(yùn)行的,因?yàn)樗o了我們力量,可以動(dòng)態(tài)的插入 .class 和 %placeholder。當(dāng)然他們不能接受像 mixin 這樣的參數(shù),上面的代碼編譯出來的 CSS:
.navigation {
margin-top: 20px;
background: #F00;
}
.selected-status, .navigation {
font-weight: bold;
}
在 Sass 的社區(qū)正在積極討論插值的局限性,誰又知道呢,也許我們很快將能夠使用這些技術(shù)也說不定呢。
注釋
Sass有兩種注釋方式,暫且將其命名為:
1.塊注釋"/*......... */"
2.行注釋 "http://"
兩者區(qū)別,前者會(huì)在編譯出來的CSS顯示,后者在編譯出來的CSS中不會(huì)顯示,示例:
//定義一個(gè)占位符
%mt5{
margin-top: 5px;
}
/*調(diào)用一個(gè)占位符*/
.box{
@extend %mt5;
}
編譯出來的CSS
.box{
margin-top: 5px;
}
/*調(diào)用一個(gè)占位符*/