Sass 快速入門 | SASS 中文網 文檔鏈接:https://www.sasscss.com/getting-started/ 前言 之前整理了一篇關於Less的,現在就來整理一下關於Sass的。 因為這兩種都是CSS的主流預處理器,當然還有Stylus。 要解釋一下什麼是Sass嗎? Sas ...
Sass 快速入門 | SASS 中文網
文檔鏈接:https://www.sasscss.com/getting-started/
前言
之前整理了一篇關於Less的,現在就來整理一下關於Sass的。
因為這兩種都是CSS的主流預處理器,當然還有Stylus。
要解釋一下什麼是Sass嗎?
Sass和Less一樣都是CSS預處理器。
CSS預處理器通俗來講就是用它們專有的語法來寫CSS,然後再通過編譯工具編譯成.css文件。
想象一下,當CSS有了變數之後該會是多麼神奇的一件事情。
Sass的特色是:
完全相容CSS3;
在CSS語言的基礎上增加變數、嵌套、混合等功能;
通過函數進行運算;
提供控制指令等功能;
自定義輸出格式;
Sass和Less有什麼區別?
Sass和Less在語法上沒什麼太大的區別。
就個人體驗來說,Sass比Less略強大、Less比Sass略簡單。
當然了,網上的網友們也總結了幾點:
1.Sass比Less更成熟,有強大的團隊在維護;
2.Sass的教程會比Less的豐富;
3.Sass有成熟的框架;
4.國內外的討論也是Sass比Less好。
不過,選擇Sass還是Less還是要基於你所在的團隊。
兩者其實都是不錯的選擇。
知識鏈
0 Sass文件尾碼名
1 變數
1.1 變數聲明
1.2 變數引用
1.3 變數名用中劃線還是下劃線分隔
2 嵌套CSS規則
2.1 父選擇器的標識符&
2.2 群組選擇器的嵌套
2.3 子組合選擇器和同層組合選擇器:>、+和~
2.4 嵌套屬性
3 導入SASS文件
3.1 使用SASS部分文件
3.2 預設變數值
3.3 嵌套導入
3.4 原生的CSS導入
4 靜默註釋
5 混合器
5.1 何時使用混合器
5.2 混合器中的CSS規則
5.3 給混合器傳參
5.4 預設參數值
6 使用選擇器繼承來精簡CSS
6.1 何時使用繼承
6.2 繼承的高級用法
6.3 繼承的工作細節
6.4 使用繼承的最佳實踐
0 Sass文件尾碼名
sass 有兩種尾碼名文件:
一種尾碼名為sass,不使用大括弧和分號;
另一種就是我們這裡使用的scss文件,這種和我們平時寫的css文件格式差不多,使用大括弧和分號。
本教程中所說的所有sass文件都指尾碼名為scss的文件。
在此也建議使用尾碼名為scss的文件,以避免sass尾碼名的嚴格格式要求報錯。
區別就是這樣子:
1 變數
你可以把反覆使用的css屬性值 定義成變數,然後通過變數名來引用它們,而無需重覆書寫這一屬性值。
或者,對於僅使用過一 次的屬性值,你可以賦予其一個易懂的變數名,讓人一眼就知道這個屬性值的用途。
sass使用$符號來標識變數(老版本的sass使用!來標識變數)。
1.1 變數聲明
$highlight-color: #F90;
任何可以用作css屬性值的賦值都 可以用作sass的變數值,
甚至是以空格分割的多個屬性值,如$basic-border: 1px solid black;,
或以逗號分割的多個屬性值,如$plain-font: "Myriad Pro"、Myriad、"Helvetica Neue"、Helvetica、"Liberation Sans"、Arial和sans-serif; sans-serif;。
這時變 量還沒有生效,除非你引用這個變數。
與CSS屬性不同,變數可以在css規則塊定義之外存在。
當變數定義在css規則塊內,那麼該變數只能在此規則塊內使用。
$nav-color: #F90; nav { $width: 100px; width: $width; color: $nav-color; } //編譯後 nav { width: 100px; color: #F90; }
在這段代碼中,
$nav-color這個變數定義在了規則塊外邊,所以在這個樣式表中都可以像nav規則塊那樣引用它。
$width這個變數定義在了nav的{ }規則塊內,所以它只能在nav規則塊內使用。
這意味著是你可以在樣式表的其他地方定義和使用$width變數,不會對這裡造成影響。
1.2 變數引用
凡是css屬性的標準值(比如說1px或者bold)可存在的地方,變數就可以使用。
css生成時,變數會被它們的值所替代。
之後,如果你需要一個不同的值,只需要改變這個變數的值,則所有引用此變數的地方生成的值都會隨之改變。
$highlight-color: #F90; .selected { border: 1px solid $highlight-color; } //編譯後 .selected { border: 1px solid #F90; }
在聲明變數時,變數值也可以引用其他變數。
當你通過粒度區分,為不同的值取不同名字時,這相當有用。
下例在獨立的顏色值粒度上定義了一個變數,且在另一個更複雜的邊框值粒度上也定義了一個變數:
$highlight-color: #F90; $highlight-border: 1px solid $highlight-color; .selected { border: $highlight-border; } //編譯後 .selected { border: 1px solid #F90; }
1.3 變數名用中劃線還是下劃線分隔
sass的變數名可以與css中的屬性名和選擇器名稱相同,包括中劃線和下劃線。
這完全取決於個人的喜好,有些人喜歡使用中劃線來分隔變數中的多個詞。
使用中劃線的方式更為普遍,這也是compass和本文都用的方式。
不過,sass並不想強迫任何人一定使用中劃線或下劃線,所以這兩種用法相互相容。
用中劃線聲明的變數可以使用下劃線的方式引用,反之亦然。
這意味著即使compass選擇用中劃線的命名方式,這並不影響你在使用compass的樣式中用下劃線的命名方式進行引用:
$link-color: blue; a { color: $link_color; } // 編譯後 a { color: blue; }
在上例中,$link-color和$link_color其實指向的是同一個變數。
實際上,在sass的大 多數地方,中劃線命名的內容和下劃線命名的內容是互通的,除了變數,也包括對混合器和Sass函數的命名。
但是在sass中純css部分不互通,比如類名、ID或屬性名。
2 嵌套CSS規則
css中重覆寫選擇器是非常惱人的。
如果要寫一大串指向頁面中同一塊的樣式時,往往需要 一遍又一遍地寫同一個ID:
#content article h1 { color: #333 } #content article p { margin-bottom: 1.4em } #content aside { background-color: #EEE }
像這種情況,sass可以讓你只寫一遍,且使樣式可讀性更高。
在Sass中,你可以像俄羅斯套娃那樣在規則塊中嵌套規則塊。
sass在輸出css時會幫你把這些嵌套規則處理好,避免你的重覆書寫。
#content { article { h1 { color: #333 } p { margin-bottom: 1.4em } } aside { background-color: #EEE } } // 編譯後 #content article h1 { color: #333 } #content article p { margin-bottom: 1.4em } #content aside { background-color: #EEE }
一個給定的規則塊,既可以像普通的CSS那樣包含屬性,又可以嵌套其他規則塊。
當你同時要為一個容器元素及其子元素編寫特定樣式時,這種能力就非常有用了。
#content { background-color: #f5f5f5; aside { background-color: #eee } }
大多數情況下這種簡單的嵌套都沒問題,但是有些場景下不行,比如你想要在嵌套的選擇器裡邊立刻應用一個類似於:hover的偽類。
為瞭解決這種以及其他情況,sass提供了一個特殊結構&。
2.1 父選擇器的標識符&
一般情況下,sass在解開一個嵌套規則時就會把父選擇器(#content)通過一個空格連接到子選擇器的前邊(article和aside)形成(#content article和#content aside)。
這種在CSS裡邊被稱為後代選擇器,因為它選擇ID為content的元素內所有命中選擇器article和aside的元素。
但在有些情況下你卻不會希望sass使用這種後代選擇器的方式生成這種連接。
最常見的一種情況是當你為鏈接之類的元素寫:hover這種偽類時,你並不希望以後代選擇器的方式連接。
比如說,下麵這種情況sass就無法正常工作:
article a { color: blue; :hover { color: red } }
解決之道為使用一個特殊的sass選擇器,即父選擇器。
在使用嵌套規則時,父選擇器能對於嵌套規則如何解開提供更好的控制。
它就是一個簡單的&符號,且可以放在任何一個選擇器可出現的地方,比如h1放在哪,它就可以放在哪。
article a { color: blue; &:hover { color: red } }
當包含父選擇器標識符的嵌套規則被打開時,它不會像後代選擇器那樣進行拼接,而是&被父選擇器直接替換:
article a { color: blue } article a:hover { color: red }
在為父級選擇器添加:hover等偽類時,這種方式非常有用。
同時父選擇器標識符還有另外一種用法,你可以在父選擇器之前添加選擇器。
舉例來說,當用戶在使用IE瀏覽器時,你會通過JavaScript在<body>標簽上添加一個ie的類名,為這種情況編寫特殊的樣式如下:
#content aside { color: red; body.ie & { color: green } } // 編譯後 #content aside {color: red}; body.ie #content aside { color: green }
2.2 群組選擇器的嵌套
nav, aside { a {color: blue} } // 編譯後 nav a, aside a {color: blue}
2.3 子組合選擇器和同層組合選擇器:>、+和~
article section { margin: 5px } article > section { border: 1px solid #ccc }
第一個選擇器會選擇article下的所有命中section選擇器的元素。
第二個選擇器只會選擇article下緊跟著的子元素中命中section選擇器的元素。
選擇header元素後緊跟的p元素:
header + p { font-size: 1.1em }
選擇所有跟在article後的同層article元素,不管它們之間隔了多少其他元素:
article ~ article { border-top: 1px dashed #ccc }
article { ~ article { border-top: 1px dashed #ccc } > section { background: #eee } dl > { dt { color: #333 } dd { color: #555 } } nav + & { margin-top: 0 } } // 編譯後 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 }
2.4 嵌套屬性
在sass中,除了CSS選擇器,屬性也可以進行嵌套。
儘管編寫屬性涉及的重覆不像編寫選擇器那麼糟糕,但是要反覆寫border-style、border-width、border-color以及border-*等也是非常煩人的。
在sass中,你只需敲寫一遍border:
nav { border: { style: solid; width: 1px; color: #ccc; } } // 編譯後 nav { border-style: solid; border-width: 1px; border-color: #ccc; }
nav { border: 1px solid #ccc { left: 0px; right: 0px; } } // 編譯後 nav { border: 1px solid #ccc; border-left: 0px; border-right: 0px; }
3 導入SASS文件
css有一個特別不常用的特性,即@import規則,它允許在一個css文件中導入其他css文件。
然而,後果是只有執行到@import時,瀏覽器才會去下載其他css文件,這導致頁面載入起來特別慢。
sass也有一個@import規則,但不同的是,sass的@import規則在生成css文件時就把相關文件導入進來。
這意味著所有相關的樣式被歸納到了同一個css文件中,而無需發起額外的下載請求。
另外,所有在被導入文件中定義的變數和混合器均可在導入文件中使用。
使用sass的@import規則並不需要指明被導入文件的全名。
你可以省略.sass或.scss文件尾碼。
這樣,在不修改樣式表的前提下,你完全可以隨意修改你或別人寫的被導入的sass樣式文件語法,在sass和scss語法之間隨意切換。
舉例來說,@import"sidebar";這條命令將把sidebar.scss文件中所有樣式添加到當前樣式表中。
3.1 使用SASS部分文件
當通過@import把sass樣式分散到多個文件時,你通常只想生成少數幾個css文件。
那些專門為@import命令而編寫的sass文件,並不需要生成對應的獨立css文件,這樣的sass文件稱為局部文件。
對此,sass有一個特殊的約定來命名這些文件。
此約定即,sass局部文件的文件名以下劃線開頭。
這樣,sass就不會在編譯時單獨編譯這個文件輸出css,而只把這個文件用作導入。
當你@import一個局部文件時,還可以不寫文件的全名,即省略文件名開頭的下劃線。
舉例來說,你想導入themes/_night-sky.scss這個局部文件里的變數,你只需在樣式表中寫@import "themes/night-sky";。
局部文件可以被多個不同的文件引用。
當一些樣式需要在多個頁面甚至多個項目中使用時,這非常有用。
在這種情況下,有時需要在你的樣式表中對導入的樣式稍作修改,sass有一個功能剛好可以解決這個問題,即預設變數值。
3.2 預設變數值
一般情況下,你反覆聲明一個變數,只有最後一處聲明有效且它會覆蓋前邊的值。舉例說明:
$link-color: blue; $link-color: red; a { color: $link-color; }
在上邊的例子中,超鏈接的color會被設置為red。
這可能並不是你想要的結果,假如你寫了一個可被他人通過@import導入的sass庫文件,你可能希望導入者可以定製修改sass庫文件中的某些值。
使用sass的!default標簽可以實現這個目的。
它很像css屬性中!important標簽的對立面,不同的是!default用於變數,含義是:如果這個變數被聲明賦值了,那就用它聲明的值,否則就用這個預設值。
$fancybox-width: 400px !default; .fancybox { width: $fancybox-width; }
在上例中,如果用戶在導入你的sass局部文件之前聲明瞭一個$fancybox-width變數,那麼你的局部文件中對$fancybox-width賦值400px的操作就無效。
如果用戶沒有做這樣的聲明,則$fancybox-width將預設為400px。
3.3 嵌套導入
跟原生的css不同,sass允許@import命令寫在css規則內。
這種導入方式下,生成對應的css文件時,局部文件會被直接插入到css規則內導入它的地方。
舉例說明,有一個名為_blue-theme.scss的局部文件,內容如下:
aside { background: blue; color: white; }
然後把它導入到一個CSS規則內,如下所示:
.blue-theme {@import "blue-theme"}
生成的結果跟你直接在.blue-theme選擇器內寫_blue-theme.scss文件的內容完全一樣。
.blue-theme { aside { background: blue; color: #fff; } }
被導入的局部文件中定義的所有變數和混合器,也會在這個規則範圍內生效。
這些變數和混合器不會全局有效,這樣我們就可以通過嵌套導入只對站點中某一特定區域運用某種顏色主題或其他通過變數配置的樣式。
3.4 原生的CSS導入
由於sass相容原生的css,所以它也支持原生的CSS@import。
儘管通常在sass中使用@import時,sass會嘗試找到對應的sass文件並導入進來,但在下列三種情況下會生成原生的CSS@import,儘管這會造成瀏覽器解析css時的額外下載:
被導入文件的名字以.css結尾;
被導入文件的名字是一個URL地址(比如http://www.sass.hk/css/css.css),由此可用谷歌字體API提供的相應服務;
被導入文件的名字是CSS的url()值。
這就是說,你不能用sass的@import直接導入一個原始的css文件,因為sass會認為你想用css原生的@import。
但是,因為sass的語法完全相容css,所以你可以把原始的css文件改名為.scss尾碼,即可直接導入了。
文件導入是保證sass的代碼可維護性和可讀性的重要一環。
次之但亦非常重要的就是註釋了。
註釋可以幫助樣式作者記錄寫sass的過程中的想法。
在原生的css中,註釋對於其他人是直接可見的,但sass提供了一種方式可在生成的css文件中按需抹掉相應的註釋。
4 靜默註釋
css中註釋的作用包括幫助你組織樣式、以後你看自己的代碼時明白為什麼這樣寫,以及簡單的樣式說明。
但是,你並不希望每個瀏覽網站源碼的人都能看到所有註釋。
sass另外提供了一種不同於css標準註釋格式/* ... */的註釋語法,即靜默註釋,其內容不會出現在生成的css文件中。
靜默註釋的語法跟JavaScript`Java等類C的語言中單行註釋的語法相同,它們以//開頭,註釋內容直到行末。
body { color: #333; // 這種註釋內容不會出現在生成的css文件中 padding: 0; /* 這種註釋內容會出現在生成的css文件中 */ }
實際上,css的標準註釋格式/* ... */內的註釋內容亦可在生成的css文件中抹去。
當註釋出現在原生css不允許的地方,如在css屬性或選擇器中,sass將不知如何將其生成到對應css文件中的相應位置,於是這些註釋被抹掉。
body { color /* 這塊註釋內容不會出現在生成的css中 */: #333; padding: 1; /* 這塊註釋內容也不會出現在生成的css中 */ 0; }
5 混合器
如果你的整個網站中有幾處小小的樣式類似(例如一致的顏色和字體),那麼使用變數來統一處理這種情況是非常不錯的選擇。
但是當你的樣式變得越來越複雜,你需要大段大段的重用樣式的代碼,獨立的變數就沒辦法應付這種情況了。
你可以通過sass的混合器實現大段樣式的重用。
混合器使用@mixin標識符定義。
看上去很像其他的CSS@標識符,比如說@media或者@font-face。
這個標識符給一大段樣式賦予一個名字,這樣你就可以輕易地通過引用這個名字重用這段樣式。
下邊的這段sass代碼,定義了一個非常簡單的混合器,目的是添加跨瀏覽器的圓角邊框。
@mixin rounded-corners { -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }
然後就可以在你的樣式表中通過@include來使用這個混合器,放在你希望的任何地方。
@include調用會把混合器中的所有樣式提取出來放在@include被調用的地方。
如果像下邊這樣寫:
.notice { background-color: green; border: 2px solid #00aa00; @include rounded-corners; } // 編譯後 .notice { background-color: green; border: 2px solid #00aa00; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }
5.1 何時使用混合器
利用混合器,可以很容易地在樣式表的不同地方共用樣式。
如果你發現自己在不停地重覆一段樣式,那就應該把這段樣式構造成優良的混合器,尤其是這段樣式本身就是一個邏輯單元,比如說是一組放在一起有意義的屬性。
判斷一組屬性是否應該組合成一個混合器,一條經驗法則就是你能否為這個混合器想出一個好的名字。
如果你能找到一個很好的短名字來描述這些屬性修飾的樣式,比如rounded-corners、fancy-font或者no-bullets,那麼往往能夠構造一個合適的混合器。
如果你找不到,這時候構造一個混合器可能並不合適。
混合器在某些方面跟css類很像。
都是讓你給一大段樣式命名,所以在選擇使用哪個的時候可能會產生疑惑。
最重要的區別就是類名是在html文件中應用的,而混合器是在樣式表中應用的。
這就意味著類名具有語義化含義,而不僅僅是一種展示性的描述:用來描述html元素的含義而不是html元素的外觀。
而另一方面,混合器是展示性的描述,用來描述一條css規則應用之後會產生怎樣的效果。
在之前的例子中,.notice是一個有語義的類名。
如果一個html元素有一個notice的類名,就表明瞭這個html元素的用途:向用戶展示提醒信息。
rounded-corners混合器是展示性的,它描述了包含它的css規則最終的視覺樣式,尤其是邊框角的視覺樣式。
混合器和類配合使用寫出整潔的html和css,因為使用語義化的類名亦可以幫你避免重覆使用混合器。
為了保持你的html和css的易讀性和可維護性,在寫樣式的過程中一定要銘記二者的區別。
5.2 混合器中的CSS規則
混合器中不僅可以包含屬性,也可以包含css規則,包含選擇器和選擇器中的屬性,如下代碼:
@mixin no-bullets { list-style: none; li { list-style-image: none; list-style-type: none; margin-left: 0px; } }
當一個包含css規則的混合器通過@include包含在一個父規則中時,在混合器中的規則最終會生成父規則中的嵌套規則。
舉個例子,看看下邊的sass代碼,這個例子中使用了no-bullets這個混合器:
ul.plain { color: #444; @include no-bullets; }
sass的@include指令會將引入混合器的那行代碼替換成混合器裡邊的內容。
最終,上邊的例子如下代碼:
ul.plain { color: #444; list-style: none; } ul.plain li { list-style-image: none; list-style-type: none; margin-left: 0px; }
混合器中的規則甚至可以使用sass的父選擇器標識符&。
使用起來跟不用混合器時一樣,sass解開嵌套規則時,用父規則中的選擇器替代&。
5.3 給混合器傳參
混合器並不一定總得生成相同的樣式。
可以通過在@include混合器時給混合器傳參,來定製混合器生成的精確樣式。
當@include混合器時,參數其實就是可以賦值給css屬性值的變數。
如果你寫過JavaScript,這種方式跟JavaScript的function很像:
@mixin link-colors($normal, $hover, $visited) { color: $normal; &:hover { color: $hover; } &:visited { color: $visited; } }
當混合器被@include時,你可以把它當作一個css函數來傳參。
如果你像下邊這樣寫:
a { @include link-colors(blue, red, green); } // 編譯後 a { color: blue; } a:hover { color: red; } a:visited { color: green; }
當你@include混合器時,有時候可能會很難區分每個參數是什麼意思,參數之間是一個什麼樣的順序。
為瞭解決這個問題,sass允許通過語法$name: value的形式指定每個參數的值。
這種形式的傳參,參數順序就不必再在乎了,只需要保證沒有漏掉參數即可:
a { @include link-colors( $normal: blue, $visited: green, $hover: red ); }
5.4 預設參數值
@mixin link-colors($normal, $hover:$normal, $visited:$normal) { color: $normal; &:hover { color: $hover; } &:visited { color: $visited; } }
如果像下邊這樣調用:@include link-colors(red) $hover和$visited也會被自動賦值為red。
混合器只是sass樣式重用特性中的一個。
我們已經瞭解到混合器主要用於樣式展示層的重用,如果你想重用語義化的類呢?
這就涉及sass的另一個重要的重用特性:選擇器繼承。
6 使用選擇器繼承來精簡CSS
使用sass的時候,最後一個減少重覆的主要特性就是選擇器繼承。
基於Nicole Sullivan面向對象的css的理念,選擇器繼承是說一個選擇器可以繼承為另一個選擇器定義的所有樣式。
這個通過@extend語法實現,如下代碼:
// 通過選擇器繼承繼承樣式 .error { border: 1px red; background-color: #fdd; } .seriousError { @extend .error; border-width: 3px; }
在上邊的代碼中,.seriousError將會繼承樣式表中任何位置處為.error定義的所有樣式。
以class="seriousError" 修飾的html元素最終的展示效果就好像是class="seriousError error"。
相關元素不僅會擁有一個3px寬的邊框,而且這個邊框將變成紅色的,這個元素同時還會有一個淺紅色的背景,因為這些都是在.error裡邊定義的樣式。
.seriousError不僅會繼承.error自身的所有樣式,任何跟.error有關的組合選擇器樣式也會被.seriousError以組合選擇器的形式繼承,如下代碼:
//.seriousError從.error繼承樣式 .error a{ //應用到.seriousError a color: red; font-weight: 100; } h1.error { //應用到hl.seriousError font-size: 1.2rem; }
6.1 何時使用繼承
因為繼承是基於類的(有時是基於其他類型的選擇器),所以繼承應該是建立在語義化的關係上。
當一個元素擁有的類(比如說.seriousError)表明它屬於另一個類(比如說.error),這時使用繼承再合適不過了。
這有點抽象,所以我們從幾個方面來闡釋一下。
想象一下你正在編寫一個頁面,給html元素添加類名,你發現你的某個類(比如說.seriousError)另一個類(比如說.error)的細化。
你會怎麼做?
你可以為這兩個類分別寫相同的樣式,但是如果有大量的重覆怎麼辦?
使用sass時,我們提倡的就是不要做重覆的工作。
你可以使用一個選擇器組(比如說.error、.seriousError)給這兩個選擇器寫相同的樣式。
如果.error的所有樣式都在同一個地方,這種做法很好,但是如果是分散在樣式表的不同地方呢?
再這樣做就困難多了。
你可以使用一個混合器為這兩個類提供相同的樣式,但當.error的樣式修飾遍佈樣式表中各處時,這種做法面臨著跟使用選擇器組一樣的問題。
這兩個類也不是恰好有相同的樣式。
你應該更清晰地表達這種關係。
綜上所述你應該使用@extend。
讓.seriousError從.error繼承樣式,使兩者之間的關係非常清晰。
更重要的是無論你在樣式表的哪裡使用.error、.seriousError都會繼承其中的樣式。
6.2 繼承的高級用法
任何css規則都可以繼承其他規則,幾乎任何css規則也都可以被繼承。
大多數情況你可能只想對類使用繼承,但是有些場合你可能想做得更多。
最常用的一種高級用法是繼承一個html元素的樣式。
儘管預設的瀏覽器樣式不會被繼承,因為它們不屬於樣式表中的樣式,但是你對html元素添加的所有樣式都會被繼承。
接下來的這段代碼定義了一個名為disabled的類,樣式修飾使它看上去像一個灰掉的超鏈接。
通過繼承a這一超鏈接元素來實現:
.disabled { color: gray; @extend a; }
假如一條樣式規則繼承了一個複雜的選擇器,那麼它只會繼承這個複雜選擇器命中的元素所應用的樣式。
舉例來說,如果[email protected],那麼.important.error和h1.important.error的樣式都會被.seriousError繼承,但是.important或者.error下的樣式則不會被繼承。
這種情況下你很可能希望.seriousError能夠分別繼承.important或者.error`下的樣式。
如果一個選擇器序列(#main .seriousError)@extend另一個選擇器(.error),那麼只有完全命中#main .seriousError這個選擇器的元素才會繼承.error的樣式,就像單個類名繼承那樣。
擁有class="seriousError"的.main元素之外的元素不會受到影響。
像#main .error這種選擇器序列是不能被繼承的。
這是因為從#main .error中繼承的樣式一般情況下會跟直接從.error中繼承的樣式基本一致,細微的區別往往使人迷惑。
6.3 繼承的工作細節
跟變數和混合器不同,繼承不是僅僅用css樣式替換@extend處的代碼那麼簡單。
為了不讓你對生成的css感覺奇怪,對這背後的工作原理有一定瞭解是非常重要的。
@extend背後最基本的想法是,如果.seriousError @extend .error,那麼樣式表中的任何一處.error都用.error .seriousError這一選擇器組進行替換。
這就意味著相關樣式會如預期那樣應用到.error和.seriousError。
當.error出現在複雜的選擇器中,比如說h1.error.error a或者#main .sidebar input.error[type="text"],那情況就變得複雜多了,但是不用擔心,sass`已經為你考慮到了這些。
關於@extend有兩個要點你應該知道。
跟混合器相比,繼承生成的css代碼相對更少。
因為繼承僅僅是重覆選擇器,而不會重覆屬性,所以使用繼承往往比混合器生成的css體積更小。
如果你非常關心你站點的速度,請牢記這一點。
繼承遵從css層疊的規則。
當兩個不同的css規則應用到同一個html元素上時,並且這兩個不同的css規則對同一屬性的修飾存在不同的值,css層疊規則會決定應用哪個樣式。
相當直觀:通常權重更高的選擇器勝出,如果權重相同,定義在後邊的規則勝出。
混合器本身不會引起css層疊的問題,因為混合器把樣式直接放到了css規則中,而繼承存在樣式層疊的問題。
被繼承的樣式會保持原有定義位置和選擇器權重不變。
通常來說這並不會引起什麼問題,但是知道這點總沒有壞處。
6.4 使用繼承的最佳實踐
通常使用繼承會讓你的css美觀、整潔。
因為繼承只會在生成css時複製選擇器,而不會複製大段的css屬性。
但是如果你不小心,可能會讓生成的css中包含大量的選擇器複製。
避免這種情況出現的最好方法就是不要在css規則中使用後代選擇器(比如.foo .bar)去繼承css規則。
如果你這麼做,同時被繼承的css規則有通過後代選擇器修飾的樣式,生成css中的選擇器的數量很快就會失控:
.foo .bar { @extend .baz; } .bip .baz { a: b; }
在上邊的例子中,sass必須保證應用到.baz的樣式同時也要應用到.foo .bar(位於class="foo"的元素內的class="bar"的元素)。
例子中有一條應用到.bip .baz(位於class="bip"的元素內的class="baz"的元素)的css規則。
當這條規則應用到.foo .bar時,可能存在三種情況,如下代碼:
<!-- 繼承可能迅速變複雜 --> <!-- Case 1 --> <div class="foo"> <div class="bip"> <div class="bar">...</div> </div> </div> <!-- Case 2 --> <div class="bip"> <div class="foo"> <div class="bar">...</div> </div> </div> <!-- Case 3 --> <div class="foo bip"> <div class="bar">...</div> </div>
為了應付這些情況,sass必鬚生成三種選擇器組合(僅僅是.bip .foo .bar不能覆蓋所有情況)。
如果任何一條規則裡邊的後代選擇器再長一點,sass需要考慮的情況就會更多。
實際上sass並不總是會生成所有可能的選擇器組合,即使是這樣,選擇器的個數依然可能會變得相當大,所以如果允許,儘可能避免這種用法。
值得一提的是,只要你想,你完全可以放心地繼承有後代選擇器修飾規則的選擇器,不管後代選擇器多長,但有一個前提就是,不要用後代選擇器去繼承。